eb-evaluation 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eb_evaluation-0.1.1/LICENSE +28 -0
- eb_evaluation-0.1.1/PKG-INFO +169 -0
- eb_evaluation-0.1.1/README.md +148 -0
- eb_evaluation-0.1.1/pyproject.toml +40 -0
- eb_evaluation-0.1.1/setup.cfg +4 -0
- eb_evaluation-0.1.1/src/eb_evaluation/__init__.py +82 -0
- eb_evaluation-0.1.1/src/eb_evaluation/adjustment/__init__.py +25 -0
- eb_evaluation-0.1.1/src/eb_evaluation/adjustment/_utils.py +168 -0
- eb_evaluation-0.1.1/src/eb_evaluation/adjustment/readiness_adjustment.py +652 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/__init__.py +40 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/cost_ratio.py +224 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/entity.py +250 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/group.py +216 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/hierarchy.py +198 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/panel.py +141 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/sensitivity.py +192 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/single.py +110 -0
- eb_evaluation-0.1.1/src/eb_evaluation/dataframe/tolerance.py +674 -0
- eb_evaluation-0.1.1/src/eb_evaluation/features/__init__.py +23 -0
- eb_evaluation-0.1.1/src/eb_evaluation/features/feature_engineer.py +371 -0
- eb_evaluation-0.1.1/src/eb_evaluation/model_selection/__init__.py +43 -0
- eb_evaluation-0.1.1/src/eb_evaluation/model_selection/auto_engine.py +299 -0
- eb_evaluation-0.1.1/src/eb_evaluation/model_selection/compare.py +419 -0
- eb_evaluation-0.1.1/src/eb_evaluation/model_selection/cwsl_regressor.py +428 -0
- eb_evaluation-0.1.1/src/eb_evaluation/model_selection/electric_barometer.py +499 -0
- eb_evaluation-0.1.1/src/eb_evaluation/utils/__init__.py +29 -0
- eb_evaluation-0.1.1/src/eb_evaluation/utils/validation.py +100 -0
- eb_evaluation-0.1.1/src/eb_evaluation.egg-info/PKG-INFO +169 -0
- eb_evaluation-0.1.1/src/eb_evaluation.egg-info/SOURCES.txt +30 -0
- eb_evaluation-0.1.1/src/eb_evaluation.egg-info/dependency_links.txt +1 -0
- eb_evaluation-0.1.1/src/eb_evaluation.egg-info/requires.txt +7 -0
- eb_evaluation-0.1.1/src/eb_evaluation.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Kyle Corrie
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eb-evaluation
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Electric Barometer: DataFrame-based evaluation utilities for CWSL and related metrics.
|
|
5
|
+
Author-email: "Kyle Corrie (Economistician)" <kcorrie@economistician.com>
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/Economistician/eb-evaluation
|
|
8
|
+
Project-URL: Repository, https://github.com/Economistician/eb-evaluation
|
|
9
|
+
Project-URL: Issues, https://github.com/Economistician/eb-evaluation/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/Economistician/eb-docs
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy>=1.24
|
|
15
|
+
Requires-Dist: pandas>=2.0
|
|
16
|
+
Requires-Dist: eb-metrics>=0.1.1
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# Electric Barometer Evaluation (`eb-evaluation`)
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+

|
|
26
|
+
[](https://economistician.github.io/eb-docs/)
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
This repository contains the **evaluation and orchestration layer** of the
|
|
30
|
+
*Electric Barometer* ecosystem.
|
|
31
|
+
|
|
32
|
+
`eb-evaluation` sits above core metric implementations (`eb-metrics`) and
|
|
33
|
+
provides structured tools for applying Electric Barometer concepts to
|
|
34
|
+
real-world forecasting workflows, including readiness adjustment, model
|
|
35
|
+
comparison, sensitivity analysis, and dataframe-based evaluation.
|
|
36
|
+
|
|
37
|
+
Conceptual definitions and theoretical framing for the evaluation logic are
|
|
38
|
+
maintained in the companion research repository:
|
|
39
|
+
**`eb-papers`**.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Naming convention
|
|
44
|
+
|
|
45
|
+
Electric Barometer packages follow standard Python packaging conventions:
|
|
46
|
+
|
|
47
|
+
- **Distribution names** (used with `pip install`) use hyphens
|
|
48
|
+
e.g. `pip install eb-evaluation`
|
|
49
|
+
- **Python import paths** use underscores
|
|
50
|
+
e.g. `import eb_evaluation`
|
|
51
|
+
|
|
52
|
+
This distinction is intentional and consistent across the Electric Barometer
|
|
53
|
+
ecosystem.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Role Within Electric Barometer
|
|
58
|
+
|
|
59
|
+
Within the Electric Barometer ecosystem:
|
|
60
|
+
|
|
61
|
+
- **`eb-papers`** defines *concepts, frameworks, and meaning*
|
|
62
|
+
- **`eb-metrics`** implements *individual metrics*
|
|
63
|
+
- **`eb-evaluation`** orchestrates *how metrics are applied, combined, and interpreted*
|
|
64
|
+
|
|
65
|
+
This repository focuses on *evaluation logic*, not raw metric computation.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## What This Library Provides
|
|
70
|
+
|
|
71
|
+
- **Readiness adjustment logic** for modifying evaluation outputs based on
|
|
72
|
+
operational readiness signals
|
|
73
|
+
- **Model selection and comparison utilities** grounded in asymmetric loss and
|
|
74
|
+
readiness-aware metrics
|
|
75
|
+
- **Sensitivity and tolerance analysis** for cost ratios and service thresholds
|
|
76
|
+
- **DataFrame-oriented evaluation tools** for entity-level and time-based analysis
|
|
77
|
+
- **Feature engineering utilities** to support evaluation pipelines
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Scope
|
|
82
|
+
|
|
83
|
+
This repository focuses on **evaluation workflows and orchestration**, not
|
|
84
|
+
low-level metric definitions.
|
|
85
|
+
|
|
86
|
+
**In scope:**
|
|
87
|
+
- Applying EB metrics to datasets and model outputs
|
|
88
|
+
- Combining metrics into readiness-aware evaluation artifacts
|
|
89
|
+
- Model comparison and selection logic
|
|
90
|
+
- Sensitivity analysis and tolerance handling
|
|
91
|
+
|
|
92
|
+
**Out of scope:**
|
|
93
|
+
- Metric definitions and loss formulations (see `eb-metrics`)
|
|
94
|
+
- Conceptual frameworks and theory (see `eb-papers`)
|
|
95
|
+
- Model training or forecasting algorithms
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Installation
|
|
100
|
+
|
|
101
|
+
Once published, the package will be installable via PyPI:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install eb-evaluation
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For development or local use:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install -e .
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Package Structure
|
|
116
|
+
|
|
117
|
+
The repository follows a modern Python package layout:
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
eb-evaluation/
|
|
121
|
+
├── src/eb_evaluation/
|
|
122
|
+
│ ├── adjustment/ # Readiness and evaluation adjustments
|
|
123
|
+
│ ├── dataframe/ # DataFrame-based evaluation utilities
|
|
124
|
+
│ ├── features/ # Feature engineering helpers
|
|
125
|
+
│ ├── model_selection/ # Model comparison and selection logic
|
|
126
|
+
│ └── utils/ # Shared validation and helpers
|
|
127
|
+
│
|
|
128
|
+
├── tests/ # Unit tests mirroring package structure
|
|
129
|
+
├── pyproject.toml # Build and dependency configuration
|
|
130
|
+
├── README.md # Project documentation
|
|
131
|
+
└── LICENSE # BSD-3-Clause license
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Relationship to Other EB Repositories
|
|
137
|
+
|
|
138
|
+
- `eb-papers`
|
|
139
|
+
Source of truth for conceptual definitions and evaluation philosophy.
|
|
140
|
+
|
|
141
|
+
- `eb-metrics`
|
|
142
|
+
Provides the metric implementations used during evaluation.
|
|
143
|
+
|
|
144
|
+
- `eb-evaluation`
|
|
145
|
+
Orchestrates evaluation workflows using adapted models.
|
|
146
|
+
|
|
147
|
+
- `eb-adapters`
|
|
148
|
+
Ensures heterogeneous models can be evaluated consistently.
|
|
149
|
+
|
|
150
|
+
When discrepancies arise, conceptual intent in `eb-papers` should be treated as authoritative.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Development and Testing
|
|
155
|
+
|
|
156
|
+
Tests are located under the `tests/` directory and mirror the package structure.
|
|
157
|
+
|
|
158
|
+
To run the test suite:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
pytest
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Status
|
|
167
|
+
|
|
168
|
+
This package is under active development.
|
|
169
|
+
Public APIs may evolve prior to the first stable release.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Electric Barometer Evaluation (`eb-evaluation`)
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
[](https://economistician.github.io/eb-docs/)
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
This repository contains the **evaluation and orchestration layer** of the
|
|
9
|
+
*Electric Barometer* ecosystem.
|
|
10
|
+
|
|
11
|
+
`eb-evaluation` sits above core metric implementations (`eb-metrics`) and
|
|
12
|
+
provides structured tools for applying Electric Barometer concepts to
|
|
13
|
+
real-world forecasting workflows, including readiness adjustment, model
|
|
14
|
+
comparison, sensitivity analysis, and dataframe-based evaluation.
|
|
15
|
+
|
|
16
|
+
Conceptual definitions and theoretical framing for the evaluation logic are
|
|
17
|
+
maintained in the companion research repository:
|
|
18
|
+
**`eb-papers`**.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Naming convention
|
|
23
|
+
|
|
24
|
+
Electric Barometer packages follow standard Python packaging conventions:
|
|
25
|
+
|
|
26
|
+
- **Distribution names** (used with `pip install`) use hyphens
|
|
27
|
+
e.g. `pip install eb-evaluation`
|
|
28
|
+
- **Python import paths** use underscores
|
|
29
|
+
e.g. `import eb_evaluation`
|
|
30
|
+
|
|
31
|
+
This distinction is intentional and consistent across the Electric Barometer
|
|
32
|
+
ecosystem.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Role Within Electric Barometer
|
|
37
|
+
|
|
38
|
+
Within the Electric Barometer ecosystem:
|
|
39
|
+
|
|
40
|
+
- **`eb-papers`** defines *concepts, frameworks, and meaning*
|
|
41
|
+
- **`eb-metrics`** implements *individual metrics*
|
|
42
|
+
- **`eb-evaluation`** orchestrates *how metrics are applied, combined, and interpreted*
|
|
43
|
+
|
|
44
|
+
This repository focuses on *evaluation logic*, not raw metric computation.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## What This Library Provides
|
|
49
|
+
|
|
50
|
+
- **Readiness adjustment logic** for modifying evaluation outputs based on
|
|
51
|
+
operational readiness signals
|
|
52
|
+
- **Model selection and comparison utilities** grounded in asymmetric loss and
|
|
53
|
+
readiness-aware metrics
|
|
54
|
+
- **Sensitivity and tolerance analysis** for cost ratios and service thresholds
|
|
55
|
+
- **DataFrame-oriented evaluation tools** for entity-level and time-based analysis
|
|
56
|
+
- **Feature engineering utilities** to support evaluation pipelines
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Scope
|
|
61
|
+
|
|
62
|
+
This repository focuses on **evaluation workflows and orchestration**, not
|
|
63
|
+
low-level metric definitions.
|
|
64
|
+
|
|
65
|
+
**In scope:**
|
|
66
|
+
- Applying EB metrics to datasets and model outputs
|
|
67
|
+
- Combining metrics into readiness-aware evaluation artifacts
|
|
68
|
+
- Model comparison and selection logic
|
|
69
|
+
- Sensitivity analysis and tolerance handling
|
|
70
|
+
|
|
71
|
+
**Out of scope:**
|
|
72
|
+
- Metric definitions and loss formulations (see `eb-metrics`)
|
|
73
|
+
- Conceptual frameworks and theory (see `eb-papers`)
|
|
74
|
+
- Model training or forecasting algorithms
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
Once published, the package will be installable via PyPI:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install eb-evaluation
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For development or local use:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install -e .
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Package Structure
|
|
95
|
+
|
|
96
|
+
The repository follows a modern Python package layout:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
eb-evaluation/
|
|
100
|
+
├── src/eb_evaluation/
|
|
101
|
+
│ ├── adjustment/ # Readiness and evaluation adjustments
|
|
102
|
+
│ ├── dataframe/ # DataFrame-based evaluation utilities
|
|
103
|
+
│ ├── features/ # Feature engineering helpers
|
|
104
|
+
│ ├── model_selection/ # Model comparison and selection logic
|
|
105
|
+
│ └── utils/ # Shared validation and helpers
|
|
106
|
+
│
|
|
107
|
+
├── tests/ # Unit tests mirroring package structure
|
|
108
|
+
├── pyproject.toml # Build and dependency configuration
|
|
109
|
+
├── README.md # Project documentation
|
|
110
|
+
└── LICENSE # BSD-3-Clause license
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Relationship to Other EB Repositories
|
|
116
|
+
|
|
117
|
+
- `eb-papers`
|
|
118
|
+
Source of truth for conceptual definitions and evaluation philosophy.
|
|
119
|
+
|
|
120
|
+
- `eb-metrics`
|
|
121
|
+
Provides the metric implementations used during evaluation.
|
|
122
|
+
|
|
123
|
+
- `eb-evaluation`
|
|
124
|
+
Orchestrates evaluation workflows using adapted models.
|
|
125
|
+
|
|
126
|
+
- `eb-adapters`
|
|
127
|
+
Ensures heterogeneous models can be evaluated consistently.
|
|
128
|
+
|
|
129
|
+
When discrepancies arise, conceptual intent in `eb-papers` should be treated as authoritative.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Development and Testing
|
|
134
|
+
|
|
135
|
+
Tests are located under the `tests/` directory and mirror the package structure.
|
|
136
|
+
|
|
137
|
+
To run the test suite:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
pytest
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Status
|
|
146
|
+
|
|
147
|
+
This package is under active development.
|
|
148
|
+
Public APIs may evolve prior to the first stable release.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "eb-evaluation"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "Electric Barometer: DataFrame-based evaluation utilities for CWSL and related metrics."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = { text = "BSD-3-Clause" }
|
|
8
|
+
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Kyle Corrie (Economistician)", email = "kcorrie@economistician.com" }
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
dependencies = [
|
|
14
|
+
"numpy>=1.24",
|
|
15
|
+
"pandas>=2.0",
|
|
16
|
+
"eb-metrics>=0.1.1",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://github.com/Economistician/eb-evaluation"
|
|
21
|
+
Repository = "https://github.com/Economistician/eb-evaluation"
|
|
22
|
+
Issues = "https://github.com/Economistician/eb-evaluation/issues"
|
|
23
|
+
Documentation = "https://github.com/Economistician/eb-docs"
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = [
|
|
27
|
+
"pytest>=8.0",
|
|
28
|
+
"pytest-cov>=5.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["setuptools>=64", "wheel"]
|
|
33
|
+
build-backend = "setuptools.build_meta"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
pythonpath = ["src"]
|
|
40
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Electric Barometer Evaluation Toolkit (eb-evaluation).
|
|
3
|
+
|
|
4
|
+
This package provides **DataFrame-oriented evaluation, diagnostics, and
|
|
5
|
+
model-selection utilities** built around Cost-Weighted Service Loss (CWSL)
|
|
6
|
+
and related readiness metrics.
|
|
7
|
+
|
|
8
|
+
Scope
|
|
9
|
+
-----
|
|
10
|
+
The eb-evaluation package sits *above* ``eb_metrics`` in the Electric Barometer
|
|
11
|
+
architecture:
|
|
12
|
+
|
|
13
|
+
- ``eb_metrics`` defines **metric math** (CWSL, NSL, UD, HR@τ, FRS, etc.)
|
|
14
|
+
- ``eb-evaluation`` provides **tabular orchestration**, grouping logic,
|
|
15
|
+
sensitivity analysis, tolerance calibration, and model selection
|
|
16
|
+
|
|
17
|
+
Primary capabilities include:
|
|
18
|
+
|
|
19
|
+
DataFrame evaluation
|
|
20
|
+
- Single-slice and grouped CWSL computation
|
|
21
|
+
- Hierarchical evaluation across multiple aggregation levels
|
|
22
|
+
- Long-form (tidy) panel outputs for plotting and reporting
|
|
23
|
+
- Entity-aware evaluation with entity-specific cost ratios
|
|
24
|
+
- Cost-ratio (R = cu / co) sensitivity analysis
|
|
25
|
+
|
|
26
|
+
Tolerance (τ) calibration
|
|
27
|
+
- Data-driven τ estimation from historical residuals
|
|
28
|
+
- Global and entity-level τ estimation with governance guards
|
|
29
|
+
- HR@τ computation with automatically selected tolerances
|
|
30
|
+
|
|
31
|
+
Model selection
|
|
32
|
+
- Cost-aware comparison of forecast models
|
|
33
|
+
- Holdout and cross-validated selection by minimum CWSL
|
|
34
|
+
- sklearn-style wrappers for downstream pipelines
|
|
35
|
+
|
|
36
|
+
Design principles
|
|
37
|
+
-----------------
|
|
38
|
+
- **Separation of concerns**: metric definitions live in ``eb_metrics``,
|
|
39
|
+
orchestration and evaluation live here.
|
|
40
|
+
- **Operational alignment**: selection and diagnostics are driven by cost
|
|
41
|
+
and readiness, not symmetric error alone.
|
|
42
|
+
- **Deterministic & explicit**: no hidden heuristics; all behavior is
|
|
43
|
+
controlled via parameters and documented outputs.
|
|
44
|
+
|
|
45
|
+
This package is intended to be used alongside ``eb_metrics`` and
|
|
46
|
+
``eb-adapters`` as part of the broader Electric Barometer ecosystem.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from .dataframe import (
|
|
50
|
+
compute_cwsl_df,
|
|
51
|
+
evaluate_groups_df,
|
|
52
|
+
evaluate_hierarchy_df,
|
|
53
|
+
evaluate_panel_df,
|
|
54
|
+
evaluate_panel_with_entity_R,
|
|
55
|
+
compute_cwsl_sensitivity_df,
|
|
56
|
+
cwsl_sensitivity_df,
|
|
57
|
+
estimate_entity_R_from_balance,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
from .dataframe.tolerance import (
|
|
61
|
+
hr_at_tau,
|
|
62
|
+
estimate_tau,
|
|
63
|
+
estimate_entity_tau,
|
|
64
|
+
hr_auto_tau,
|
|
65
|
+
TauEstimate,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
__all__ = [
|
|
69
|
+
"compute_cwsl_df",
|
|
70
|
+
"evaluate_groups_df",
|
|
71
|
+
"evaluate_hierarchy_df",
|
|
72
|
+
"evaluate_panel_df",
|
|
73
|
+
"evaluate_panel_with_entity_R",
|
|
74
|
+
"compute_cwsl_sensitivity_df",
|
|
75
|
+
"cwsl_sensitivity_df",
|
|
76
|
+
"estimate_entity_R_from_balance",
|
|
77
|
+
"hr_at_tau",
|
|
78
|
+
"estimate_tau",
|
|
79
|
+
"estimate_entity_tau",
|
|
80
|
+
"hr_auto_tau",
|
|
81
|
+
"TauEstimate",
|
|
82
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Adjustment utilities for Electric Barometer evaluation.
|
|
3
|
+
|
|
4
|
+
The `eb_evaluation.adjustment` package contains the **Readiness Adjustment Layer (RAL)**,
|
|
5
|
+
a lightweight post-processing component that converts a baseline statistical forecast into an
|
|
6
|
+
operationally conservative *readiness forecast* via a learned multiplicative uplift.
|
|
7
|
+
|
|
8
|
+
Key ideas
|
|
9
|
+
---------
|
|
10
|
+
- **Metrics live in** `eb_metrics.metrics` (definitions only).
|
|
11
|
+
- **Adjustments live here** (evaluation / selection utilities that *consume* metrics).
|
|
12
|
+
- RAL learns an uplift by grid-searching multipliers and selecting the value that minimizes
|
|
13
|
+
**Cost-Weighted Service Loss (CWSL)** on historical data.
|
|
14
|
+
- Uplifts can be learned globally or per-segment (with a global fallback for unseen segments).
|
|
15
|
+
|
|
16
|
+
Public API
|
|
17
|
+
----------
|
|
18
|
+
- `ReadinessAdjustmentLayer`
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from .readiness_adjustment import ReadinessAdjustmentLayer
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"ReadinessAdjustmentLayer",
|
|
25
|
+
]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Internal utilities for the Readiness Adjustment Layer.
|
|
5
|
+
|
|
6
|
+
This module contains small, focused helpers used by the Readiness Adjustment Layer (RAL)
|
|
7
|
+
implementation. These utilities are **not** part of the public API and may change without
|
|
8
|
+
notice.
|
|
9
|
+
|
|
10
|
+
The intent is to keep the main algorithm (and its public surface area) in
|
|
11
|
+
`eb_evaluation.adjustment.readiness_adjustment` clean and readable.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from collections.abc import Callable, Sequence
|
|
15
|
+
from typing import Any, Union, overload
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
import pandas as pd
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
ArrayLike = Union[np.ndarray, Sequence[float], pd.Series, pd.DataFrame]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
# Array validation utilities
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
def validate_numeric_array(arr: ArrayLike, name: str = "array") -> np.ndarray:
|
|
28
|
+
"""Validate and coerce an input to a finite float NumPy array.
|
|
29
|
+
|
|
30
|
+
This helper is intentionally strict: it ensures the array is not scalar and that
|
|
31
|
+
all values are finite. This is appropriate for evaluation utilities where silent
|
|
32
|
+
propagation of NaNs can lead to misleading metric comparisons.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
arr
|
|
37
|
+
Input array-like object. Common inputs include lists, NumPy arrays, pandas Series,
|
|
38
|
+
or a single-column DataFrame.
|
|
39
|
+
name
|
|
40
|
+
Name used in error messages to make debugging easier.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
numpy.ndarray
|
|
45
|
+
A NumPy array of dtype ``float64``. The returned array may be 1D or 2D depending on
|
|
46
|
+
the input.
|
|
47
|
+
|
|
48
|
+
Raises
|
|
49
|
+
------
|
|
50
|
+
ValueError
|
|
51
|
+
If ``arr`` is scalar (0-dimensional) or contains NaN/infinite values.
|
|
52
|
+
|
|
53
|
+
Notes
|
|
54
|
+
-----
|
|
55
|
+
- If you pass a DataFrame, its underlying NumPy representation is used (i.e., you are
|
|
56
|
+
responsible for selecting appropriate columns before calling this helper).
|
|
57
|
+
- This helper does *not* drop missing values. If you need filtering behavior, perform
|
|
58
|
+
it upstream and call this only once the array should be clean.
|
|
59
|
+
"""
|
|
60
|
+
if isinstance(arr, (pd.Series, pd.DataFrame)):
|
|
61
|
+
arr = arr.to_numpy()
|
|
62
|
+
|
|
63
|
+
out = np.asarray(arr, dtype=float)
|
|
64
|
+
|
|
65
|
+
if out.ndim == 0:
|
|
66
|
+
raise ValueError(f"{name} must be an array-like (not a scalar).")
|
|
67
|
+
|
|
68
|
+
if not np.isfinite(out).all():
|
|
69
|
+
raise ValueError(f"{name} contains NaN or infinite values.")
|
|
70
|
+
|
|
71
|
+
return out
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
# Safe statistical helpers
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
def safe_mean(values: np.ndarray) -> float:
|
|
78
|
+
"""Compute a mean with a defined result for empty inputs.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
values
|
|
83
|
+
Numeric array. Typically a 1D array of values after filtering.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
float
|
|
88
|
+
The arithmetic mean of ``values``. If ``values`` is empty (``values.size == 0``),
|
|
89
|
+
returns ``0.0``.
|
|
90
|
+
|
|
91
|
+
Notes
|
|
92
|
+
-----
|
|
93
|
+
This is mainly used in group-level computations where a group may end up empty after
|
|
94
|
+
filtering invalid rows. Returning ``0.0`` is a pragmatic default for diagnostics; it
|
|
95
|
+
should not be used as a substitute for input validation in the primary metric pathway.
|
|
96
|
+
"""
|
|
97
|
+
values = np.asarray(values, dtype=float)
|
|
98
|
+
if values.size == 0:
|
|
99
|
+
return 0.0
|
|
100
|
+
return float(np.mean(values))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
# Groupby helpers
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
def groupby_apply_values(
|
|
107
|
+
df: pd.DataFrame,
|
|
108
|
+
group_cols: Union[str, Sequence[str]],
|
|
109
|
+
value_col: str,
|
|
110
|
+
func: Callable[[np.ndarray], float],
|
|
111
|
+
) -> pd.DataFrame:
|
|
112
|
+
"""Apply a numeric reducer to a column, grouped by one or more keys.
|
|
113
|
+
|
|
114
|
+
This helper groups ``df`` by ``group_cols`` and applies ``func`` to the values of
|
|
115
|
+
``value_col`` for each group. The function is called with a **validated**, finite
|
|
116
|
+
float array.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
df
|
|
121
|
+
Input DataFrame containing grouping keys and the numeric value column.
|
|
122
|
+
group_cols
|
|
123
|
+
Column name or sequence of column names to group by.
|
|
124
|
+
value_col
|
|
125
|
+
Name of the column whose values are passed to ``func``.
|
|
126
|
+
func
|
|
127
|
+
Reducer function taking a 1D NumPy array and returning a scalar (float).
|
|
128
|
+
|
|
129
|
+
Returns
|
|
130
|
+
-------
|
|
131
|
+
pandas.DataFrame
|
|
132
|
+
A tidy DataFrame with columns:
|
|
133
|
+
|
|
134
|
+
- ``group_cols`` (one column per grouping key)
|
|
135
|
+
- ``f"{value_col}_agg"`` (the aggregated scalar result)
|
|
136
|
+
|
|
137
|
+
Raises
|
|
138
|
+
------
|
|
139
|
+
KeyError
|
|
140
|
+
If ``value_col`` or any ``group_cols`` are missing from ``df``.
|
|
141
|
+
ValueError
|
|
142
|
+
If group values contain NaN/infinite values (via :func:`validate_numeric_array`).
|
|
143
|
+
|
|
144
|
+
Examples
|
|
145
|
+
--------
|
|
146
|
+
>>> out = groupby_apply_values(df, ["cluster", "daypart"], "uplift", np.mean)
|
|
147
|
+
>>> out.columns
|
|
148
|
+
Index(['cluster', 'daypart', 'uplift_agg'], dtype='object')
|
|
149
|
+
"""
|
|
150
|
+
if isinstance(group_cols, str):
|
|
151
|
+
group_cols_seq: list[str] = [group_cols]
|
|
152
|
+
else:
|
|
153
|
+
group_cols_seq = list(group_cols)
|
|
154
|
+
|
|
155
|
+
missing = [c for c in [*group_cols_seq, value_col] if c not in df.columns]
|
|
156
|
+
if missing:
|
|
157
|
+
raise KeyError(f"Missing required columns: {missing}")
|
|
158
|
+
|
|
159
|
+
agg_col = f"{value_col}_agg"
|
|
160
|
+
|
|
161
|
+
grouped = (
|
|
162
|
+
df.groupby(group_cols_seq, dropna=False)[value_col]
|
|
163
|
+
.apply(lambda s: func(validate_numeric_array(s.to_numpy(), name=value_col)))
|
|
164
|
+
.reset_index()
|
|
165
|
+
.rename(columns={value_col: agg_col})
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return grouped
|