eb-features 0.1.0__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_features-0.1.0/LICENSE +28 -0
- eb_features-0.1.0/PKG-INFO +168 -0
- eb_features-0.1.0/README.md +137 -0
- eb_features-0.1.0/pyproject.toml +59 -0
- eb_features-0.1.0/setup.cfg +4 -0
- eb_features-0.1.0/src/eb_features/__init__.py +20 -0
- eb_features-0.1.0/src/eb_features/panel/__init__.py +42 -0
- eb_features-0.1.0/src/eb_features/panel/calendar.py +193 -0
- eb_features-0.1.0/src/eb_features/panel/config.py +95 -0
- eb_features-0.1.0/src/eb_features/panel/constants.py +75 -0
- eb_features-0.1.0/src/eb_features/panel/encoders.py +91 -0
- eb_features-0.1.0/src/eb_features/panel/engineering.py +304 -0
- eb_features-0.1.0/src/eb_features/panel/lags.py +95 -0
- eb_features-0.1.0/src/eb_features/panel/rolling.py +170 -0
- eb_features-0.1.0/src/eb_features/panel/validation.py +128 -0
- eb_features-0.1.0/src/eb_features.egg-info/PKG-INFO +168 -0
- eb_features-0.1.0/src/eb_features.egg-info/SOURCES.txt +18 -0
- eb_features-0.1.0/src/eb_features.egg-info/dependency_links.txt +1 -0
- eb_features-0.1.0/src/eb_features.egg-info/requires.txt +6 -0
- eb_features-0.1.0/src/eb_features.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,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eb-features
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Feature engineering utilities for panel time-series data in the Electric Barometer ecosystem.
|
|
5
|
+
Author-email: "Kyle Corrie (Economistician)" <kcorrie@economistician.com>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/Economistician/eb-features
|
|
8
|
+
Project-URL: Repository, https://github.com/Economistician/eb-features
|
|
9
|
+
Project-URL: Issues, https://github.com/Economistician/eb-features/issues
|
|
10
|
+
Project-URL: Documentation, https://economistician.github.io/eb-docs/
|
|
11
|
+
Keywords: forecasting,features,feature-engineering,time-series,panel-data,operations-research
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: pandas>=2.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# Electric barometer Feature Engineering (`eb-features`)
|
|
33
|
+
|
|
34
|
+
**eb-features** is the feature engineering layer of the **Electric Barometer** ecosystem.
|
|
35
|
+
|
|
36
|
+
It provides a structured, opinionated set of **panel-aware feature construction utilities**
|
|
37
|
+
for time-series modeling in operational environments—contexts where *temporal structure*,
|
|
38
|
+
*entity boundaries*, and *leakage safety* matter as much as model choice itself.
|
|
39
|
+
|
|
40
|
+
This package focuses on **deterministic, stateless feature generation** for classical
|
|
41
|
+
supervised learning pipelines, producing clean, model-ready design matrices from
|
|
42
|
+
long-form panel data.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Naming convention
|
|
47
|
+
|
|
48
|
+
Electric Barometer packages follow a consistent naming convention:
|
|
49
|
+
|
|
50
|
+
- **Distribution names** (used with `pip install`) use hyphens
|
|
51
|
+
e.g. `pip install eb-features`
|
|
52
|
+
- **Python import paths** use underscores
|
|
53
|
+
e.g. `import eb_features`
|
|
54
|
+
|
|
55
|
+
This follows standard Python packaging practices and avoids ambiguity between
|
|
56
|
+
package names and module imports.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## What this package provides
|
|
61
|
+
|
|
62
|
+
### Panel-safe lag features
|
|
63
|
+
Lagged versions of the target series constructed **strictly within entity** boundaries.
|
|
64
|
+
|
|
65
|
+
- Configurable lag steps (index-based, frequency-agnostic)
|
|
66
|
+
- Deterministic naming (`lag_1`, `lag_24`, etc.)
|
|
67
|
+
- Explicit handling of missing history
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### Leakage-aware rolling statistics
|
|
72
|
+
Rolling-window summaries designed for forecasting workflows.
|
|
73
|
+
|
|
74
|
+
- Mean, sum, min, max, std, median
|
|
75
|
+
- Configurable window sizes
|
|
76
|
+
- **Leakage-safe by default** (excludes current target value)
|
|
77
|
+
- Optional early availability via `min_periods`
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### Calendar and time-derived features
|
|
82
|
+
Calendar attributes derived from timestamp columns.
|
|
83
|
+
|
|
84
|
+
- Hour, day-of-week, day-of-month, month
|
|
85
|
+
- Weekend indicators
|
|
86
|
+
- Optional cyclical encodings (sine/cosine) for periodic components
|
|
87
|
+
- Timezone-aware timestamp support
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### Passthrough regressors and static features
|
|
92
|
+
Support for mixing engineered temporal features with:
|
|
93
|
+
|
|
94
|
+
- Numeric external regressors
|
|
95
|
+
- Static entity-level metadata
|
|
96
|
+
- Automatic regressor detection when not explicitly specified
|
|
97
|
+
|
|
98
|
+
Non-numeric passthrough columns are encoded using stable, dataset-local
|
|
99
|
+
categorical codes.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Validation and guardrails
|
|
104
|
+
Built-in validation to catch common modeling errors early.
|
|
105
|
+
|
|
106
|
+
- Required-column checks
|
|
107
|
+
- Strict monotonic timestamp enforcement within entity
|
|
108
|
+
- Protection against cross-entity leakage
|
|
109
|
+
- Non-finite value detection before model handoff
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Design principles
|
|
114
|
+
|
|
115
|
+
`eb-features` is intentionally:
|
|
116
|
+
|
|
117
|
+
- **Stateless** — no fitted encoders or persisted mappings
|
|
118
|
+
- **Deterministic** — same input + config → same output
|
|
119
|
+
- **Frequency-agnostic** — works with hourly, daily, or irregular data
|
|
120
|
+
- **Panel-aware** — entity boundaries are first-class constraints
|
|
121
|
+
|
|
122
|
+
This makes it suitable for batch modeling, experimentation, and reproducible
|
|
123
|
+
forecast evaluation pipelines.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Documentation structure
|
|
128
|
+
|
|
129
|
+
- **API Reference**
|
|
130
|
+
All feature builders and utilities are documented automatically from
|
|
131
|
+
NumPy-style docstrings using `mkdocstrings`.
|
|
132
|
+
|
|
133
|
+
Conceptual motivation and modeling guidance for these features live in the
|
|
134
|
+
companion repositories:
|
|
135
|
+
|
|
136
|
+
- **eb-metrics** — operationally meaningful forecast metrics
|
|
137
|
+
- **eb-evaluation** — structured forecast evaluation workflows
|
|
138
|
+
- **eb-papers** — formal definitions and technical notes
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Intended audience
|
|
143
|
+
|
|
144
|
+
This package is intended for:
|
|
145
|
+
|
|
146
|
+
- data scientists and applied ML practitioners
|
|
147
|
+
- forecasting and demand-planning teams
|
|
148
|
+
- operations and service analytics engineers
|
|
149
|
+
- researchers working with panel time-series data
|
|
150
|
+
|
|
151
|
+
The emphasis throughout is on **correct feature construction under operational
|
|
152
|
+
constraints**, not generic time-series convenience.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Relationship to the Electric Barometer framework
|
|
157
|
+
|
|
158
|
+
`eb-features` provides the **feature engineering layer** of the Electric Barometer
|
|
159
|
+
ecosystem.
|
|
160
|
+
|
|
161
|
+
It is designed to work in concert with:
|
|
162
|
+
|
|
163
|
+
- **eb-metrics** — how forecasts are evaluated
|
|
164
|
+
- **eb-evaluation** — how forecasts are compared and selected
|
|
165
|
+
- **eb-adapters** — how forecasts integrate with external systems
|
|
166
|
+
|
|
167
|
+
Together, these components support a disciplined, end-to-end approach to
|
|
168
|
+
*forecast readiness*—from raw data, to features, to evaluation.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Electric barometer Feature Engineering (`eb-features`)
|
|
2
|
+
|
|
3
|
+
**eb-features** is the feature engineering layer of the **Electric Barometer** ecosystem.
|
|
4
|
+
|
|
5
|
+
It provides a structured, opinionated set of **panel-aware feature construction utilities**
|
|
6
|
+
for time-series modeling in operational environments—contexts where *temporal structure*,
|
|
7
|
+
*entity boundaries*, and *leakage safety* matter as much as model choice itself.
|
|
8
|
+
|
|
9
|
+
This package focuses on **deterministic, stateless feature generation** for classical
|
|
10
|
+
supervised learning pipelines, producing clean, model-ready design matrices from
|
|
11
|
+
long-form panel data.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Naming convention
|
|
16
|
+
|
|
17
|
+
Electric Barometer packages follow a consistent naming convention:
|
|
18
|
+
|
|
19
|
+
- **Distribution names** (used with `pip install`) use hyphens
|
|
20
|
+
e.g. `pip install eb-features`
|
|
21
|
+
- **Python import paths** use underscores
|
|
22
|
+
e.g. `import eb_features`
|
|
23
|
+
|
|
24
|
+
This follows standard Python packaging practices and avoids ambiguity between
|
|
25
|
+
package names and module imports.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What this package provides
|
|
30
|
+
|
|
31
|
+
### Panel-safe lag features
|
|
32
|
+
Lagged versions of the target series constructed **strictly within entity** boundaries.
|
|
33
|
+
|
|
34
|
+
- Configurable lag steps (index-based, frequency-agnostic)
|
|
35
|
+
- Deterministic naming (`lag_1`, `lag_24`, etc.)
|
|
36
|
+
- Explicit handling of missing history
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### Leakage-aware rolling statistics
|
|
41
|
+
Rolling-window summaries designed for forecasting workflows.
|
|
42
|
+
|
|
43
|
+
- Mean, sum, min, max, std, median
|
|
44
|
+
- Configurable window sizes
|
|
45
|
+
- **Leakage-safe by default** (excludes current target value)
|
|
46
|
+
- Optional early availability via `min_periods`
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Calendar and time-derived features
|
|
51
|
+
Calendar attributes derived from timestamp columns.
|
|
52
|
+
|
|
53
|
+
- Hour, day-of-week, day-of-month, month
|
|
54
|
+
- Weekend indicators
|
|
55
|
+
- Optional cyclical encodings (sine/cosine) for periodic components
|
|
56
|
+
- Timezone-aware timestamp support
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Passthrough regressors and static features
|
|
61
|
+
Support for mixing engineered temporal features with:
|
|
62
|
+
|
|
63
|
+
- Numeric external regressors
|
|
64
|
+
- Static entity-level metadata
|
|
65
|
+
- Automatic regressor detection when not explicitly specified
|
|
66
|
+
|
|
67
|
+
Non-numeric passthrough columns are encoded using stable, dataset-local
|
|
68
|
+
categorical codes.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### Validation and guardrails
|
|
73
|
+
Built-in validation to catch common modeling errors early.
|
|
74
|
+
|
|
75
|
+
- Required-column checks
|
|
76
|
+
- Strict monotonic timestamp enforcement within entity
|
|
77
|
+
- Protection against cross-entity leakage
|
|
78
|
+
- Non-finite value detection before model handoff
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Design principles
|
|
83
|
+
|
|
84
|
+
`eb-features` is intentionally:
|
|
85
|
+
|
|
86
|
+
- **Stateless** — no fitted encoders or persisted mappings
|
|
87
|
+
- **Deterministic** — same input + config → same output
|
|
88
|
+
- **Frequency-agnostic** — works with hourly, daily, or irregular data
|
|
89
|
+
- **Panel-aware** — entity boundaries are first-class constraints
|
|
90
|
+
|
|
91
|
+
This makes it suitable for batch modeling, experimentation, and reproducible
|
|
92
|
+
forecast evaluation pipelines.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Documentation structure
|
|
97
|
+
|
|
98
|
+
- **API Reference**
|
|
99
|
+
All feature builders and utilities are documented automatically from
|
|
100
|
+
NumPy-style docstrings using `mkdocstrings`.
|
|
101
|
+
|
|
102
|
+
Conceptual motivation and modeling guidance for these features live in the
|
|
103
|
+
companion repositories:
|
|
104
|
+
|
|
105
|
+
- **eb-metrics** — operationally meaningful forecast metrics
|
|
106
|
+
- **eb-evaluation** — structured forecast evaluation workflows
|
|
107
|
+
- **eb-papers** — formal definitions and technical notes
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Intended audience
|
|
112
|
+
|
|
113
|
+
This package is intended for:
|
|
114
|
+
|
|
115
|
+
- data scientists and applied ML practitioners
|
|
116
|
+
- forecasting and demand-planning teams
|
|
117
|
+
- operations and service analytics engineers
|
|
118
|
+
- researchers working with panel time-series data
|
|
119
|
+
|
|
120
|
+
The emphasis throughout is on **correct feature construction under operational
|
|
121
|
+
constraints**, not generic time-series convenience.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Relationship to the Electric Barometer framework
|
|
126
|
+
|
|
127
|
+
`eb-features` provides the **feature engineering layer** of the Electric Barometer
|
|
128
|
+
ecosystem.
|
|
129
|
+
|
|
130
|
+
It is designed to work in concert with:
|
|
131
|
+
|
|
132
|
+
- **eb-metrics** — how forecasts are evaluated
|
|
133
|
+
- **eb-evaluation** — how forecasts are compared and selected
|
|
134
|
+
- **eb-adapters** — how forecasts integrate with external systems
|
|
135
|
+
|
|
136
|
+
Together, these components support a disciplined, end-to-end approach to
|
|
137
|
+
*forecast readiness*—from raw data, to features, to evaluation.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "eb-features"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Feature engineering utilities for panel time-series data in the Electric Barometer ecosystem."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "BSD-3-Clause"
|
|
8
|
+
license-files = ["LICENSE*"]
|
|
9
|
+
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Kyle Corrie (Economistician)", email = "kcorrie@economistician.com" }
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
dependencies = [
|
|
15
|
+
"numpy>=1.24",
|
|
16
|
+
"pandas>=2.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
keywords = ["forecasting", "features", "feature-engineering", "time-series", "panel-data", "operations-research"]
|
|
20
|
+
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Development Status :: 3 - Alpha",
|
|
23
|
+
"Intended Audience :: Science/Research",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Topic :: Scientific/Engineering",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/Economistician/eb-features"
|
|
36
|
+
Repository = "https://github.com/Economistician/eb-features"
|
|
37
|
+
Issues = "https://github.com/Economistician/eb-features/issues"
|
|
38
|
+
Documentation = "https://economistician.github.io/eb-docs/"
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.0",
|
|
43
|
+
"pytest-cov>=5.0",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["setuptools>=64", "wheel"]
|
|
48
|
+
build-backend = "setuptools.build_meta"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools]
|
|
51
|
+
package-dir = {"" = "src"}
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
where = ["src"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
pythonpath = ["src"]
|
|
58
|
+
addopts = "-ra"
|
|
59
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Feature engineering utilities for the Electric Barometer ecosystem.
|
|
5
|
+
|
|
6
|
+
This package provides modular, domain-agnostic feature engineering components
|
|
7
|
+
used across forecasting, evaluation, and operational modeling workflows.
|
|
8
|
+
|
|
9
|
+
Subpackages
|
|
10
|
+
-----------
|
|
11
|
+
panel
|
|
12
|
+
Feature engineering utilities for panel (entity Ă— timestamp) time-series data.
|
|
13
|
+
|
|
14
|
+
Notes
|
|
15
|
+
-----
|
|
16
|
+
This package intentionally exposes a small public API. Most functionality is
|
|
17
|
+
accessed through subpackages such as `eb_features.panel`.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
__all__ = []
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Panel time-series feature engineering.
|
|
5
|
+
|
|
6
|
+
This subpackage provides lightweight, frequency-agnostic feature engineering utilities
|
|
7
|
+
for *panel* time-series data, i.e., data indexed by:
|
|
8
|
+
|
|
9
|
+
- an **entity** identifier (store, SKU, customer, sensor, etc.), and
|
|
10
|
+
- a **timestamp** column
|
|
11
|
+
|
|
12
|
+
The primary public interface is:
|
|
13
|
+
|
|
14
|
+
- [`FeatureConfig`][eb_features.panel.engineering.FeatureConfig]: declarative feature configuration
|
|
15
|
+
- [`FeatureEngineer`][eb_features.panel.engineering.FeatureEngineer]: stateless transformer that
|
|
16
|
+
produces a model-ready ``(X, y, feature_names)`` triple from a long-form DataFrame.
|
|
17
|
+
|
|
18
|
+
Design goals
|
|
19
|
+
------------
|
|
20
|
+
- **Stateless**: no fit/transform lifecycle; features are generated deterministically from inputs.
|
|
21
|
+
- **Frequency-agnostic**: lags and rolling windows are expressed in index steps, not wall-clock units.
|
|
22
|
+
- **Leakage-aware**: feature construction is intended to use only information available at or
|
|
23
|
+
before prediction time (depending on configuration and implementation details).
|
|
24
|
+
|
|
25
|
+
Notes
|
|
26
|
+
-----
|
|
27
|
+
This subpackage is intentionally conservative in scope. It focuses on producing features suitable
|
|
28
|
+
for classical supervised learning pipelines (tree models, linear models, shallow neural nets) that
|
|
29
|
+
expect a fixed-width design matrix.
|
|
30
|
+
|
|
31
|
+
See Also
|
|
32
|
+
--------
|
|
33
|
+
- [`eb_features.panel.engineering.FeatureEngineer`][eb_features.panel.engineering.FeatureEngineer]
|
|
34
|
+
- [`eb_features.panel.engineering.FeatureConfig`][eb_features.panel.engineering.FeatureConfig]
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from eb_features.panel.engineering import FeatureConfig, FeatureEngineer
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"FeatureConfig",
|
|
41
|
+
"FeatureEngineer",
|
|
42
|
+
]
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Calendar and time-derived features for panel time series.
|
|
5
|
+
|
|
6
|
+
This module provides utilities to derive calendar/time features from a timestamp column.
|
|
7
|
+
It is designed for *panel* time-series data (entity Ă— timestamp) and is typically used
|
|
8
|
+
as part of a broader feature engineering pipeline.
|
|
9
|
+
|
|
10
|
+
Supported base calendar features
|
|
11
|
+
--------------------------------
|
|
12
|
+
Given a timestamp column ``timestamp_col``:
|
|
13
|
+
|
|
14
|
+
- ``"hour"``: Hour of day in ``[0, 23]``
|
|
15
|
+
- ``"dow"``: Day of week in ``[0, 6]`` where Monday=0 (pandas convention)
|
|
16
|
+
- ``"dom"``: Day of month in ``[1, 31]``
|
|
17
|
+
- ``"month"``: Month in ``[1, 12]``
|
|
18
|
+
- ``"is_weekend"``: Weekend indicator (Saturday/Sunday) as ``0/1``
|
|
19
|
+
|
|
20
|
+
Optional cyclical encodings
|
|
21
|
+
---------------------------
|
|
22
|
+
Certain calendar attributes are periodic and can be represented with sine/cosine pairs:
|
|
23
|
+
|
|
24
|
+
- hour (period 24):
|
|
25
|
+
|
|
26
|
+
$$
|
|
27
|
+
\sin\left(2\pi \frac{\mathrm{hour}}{24}\right),\quad
|
|
28
|
+
\cos\left(2\pi \frac{\mathrm{hour}}{24}\right)
|
|
29
|
+
$$
|
|
30
|
+
|
|
31
|
+
- day of week (period 7):
|
|
32
|
+
|
|
33
|
+
$$
|
|
34
|
+
\sin\left(2\pi \frac{\mathrm{dow}}{7}\right),\quad
|
|
35
|
+
\cos\left(2\pi \frac{\mathrm{dow}}{7}\right)
|
|
36
|
+
$$
|
|
37
|
+
|
|
38
|
+
These encodings are added only when:
|
|
39
|
+
- the corresponding base feature (hour or dow) is present, and
|
|
40
|
+
- ``use_cyclical_time=True``.
|
|
41
|
+
|
|
42
|
+
Notes
|
|
43
|
+
-----
|
|
44
|
+
- Feature construction is *stateless*: functions operate only on the provided DataFrame.
|
|
45
|
+
- Time features are derived from ``pandas.to_datetime`` conversion of ``timestamp_col``.
|
|
46
|
+
Timezone-aware timestamps are supported; feature values reflect the timestamp's local
|
|
47
|
+
representation as stored in the column.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
from typing import Iterable, List, Sequence, Tuple
|
|
51
|
+
|
|
52
|
+
import numpy as np
|
|
53
|
+
import pandas as pd
|
|
54
|
+
|
|
55
|
+
from eb_features.panel.constants import (
|
|
56
|
+
ALLOWED_CALENDAR_FEATURES,
|
|
57
|
+
DOW_PERIOD,
|
|
58
|
+
HOUR_PERIOD,
|
|
59
|
+
WEEKEND_DAYS,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def add_calendar_features(
|
|
64
|
+
df: pd.DataFrame,
|
|
65
|
+
*,
|
|
66
|
+
timestamp_col: str,
|
|
67
|
+
calendar_features: Sequence[str],
|
|
68
|
+
use_cyclical_time: bool = True,
|
|
69
|
+
) -> Tuple[pd.DataFrame, List[str], List[str]]:
|
|
70
|
+
r"""
|
|
71
|
+
Add calendar/time-derived features to a DataFrame.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
df : pandas.DataFrame
|
|
76
|
+
Input DataFrame containing a timestamp column.
|
|
77
|
+
timestamp_col : str
|
|
78
|
+
Name of the timestamp column.
|
|
79
|
+
calendar_features : Sequence[str]
|
|
80
|
+
Base calendar features to derive. Allowed values are:
|
|
81
|
+
``{"hour", "dow", "dom", "month", "is_weekend"}``.
|
|
82
|
+
use_cyclical_time : bool, default True
|
|
83
|
+
If True, add sine/cosine encodings for hour and/or day-of-week when those
|
|
84
|
+
base features are included.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
df_out : pandas.DataFrame
|
|
89
|
+
Copy of ``df`` with the requested calendar features added as columns.
|
|
90
|
+
feature_cols : list[str]
|
|
91
|
+
Names of all features added by this call, including cyclical encodings (if any).
|
|
92
|
+
calendar_cols : list[str]
|
|
93
|
+
Names of base calendar feature columns added (excludes cyclical encodings).
|
|
94
|
+
|
|
95
|
+
Raises
|
|
96
|
+
------
|
|
97
|
+
KeyError
|
|
98
|
+
If ``timestamp_col`` is not present in ``df``.
|
|
99
|
+
ValueError
|
|
100
|
+
If an unsupported calendar feature is requested.
|
|
101
|
+
|
|
102
|
+
Notes
|
|
103
|
+
-----
|
|
104
|
+
The derived columns are currently named:
|
|
105
|
+
|
|
106
|
+
- ``hour``
|
|
107
|
+
- ``dayofweek`` (for requested ``"dow"``)
|
|
108
|
+
- ``dayofmonth`` (for requested ``"dom"``)
|
|
109
|
+
- ``month``
|
|
110
|
+
- ``is_weekend``
|
|
111
|
+
|
|
112
|
+
This naming is stable and intended to be referenced by downstream steps.
|
|
113
|
+
"""
|
|
114
|
+
if timestamp_col not in df.columns:
|
|
115
|
+
raise KeyError(f"Timestamp column {timestamp_col!r} not found in DataFrame.")
|
|
116
|
+
|
|
117
|
+
_validate_calendar_features(calendar_features)
|
|
118
|
+
|
|
119
|
+
df_out = df.copy()
|
|
120
|
+
ts = pd.to_datetime(df_out[timestamp_col])
|
|
121
|
+
|
|
122
|
+
calendar_cols: List[str] = []
|
|
123
|
+
feature_cols: List[str] = []
|
|
124
|
+
|
|
125
|
+
for name in calendar_features:
|
|
126
|
+
if name == "hour":
|
|
127
|
+
col = "hour"
|
|
128
|
+
df_out[col] = ts.dt.hour.astype("int16")
|
|
129
|
+
calendar_cols.append(col)
|
|
130
|
+
elif name == "dow":
|
|
131
|
+
col = "dayofweek"
|
|
132
|
+
df_out[col] = ts.dt.dayofweek.astype("int16")
|
|
133
|
+
calendar_cols.append(col)
|
|
134
|
+
elif name == "dom":
|
|
135
|
+
col = "dayofmonth"
|
|
136
|
+
df_out[col] = ts.dt.day.astype("int16")
|
|
137
|
+
calendar_cols.append(col)
|
|
138
|
+
elif name == "month":
|
|
139
|
+
col = "month"
|
|
140
|
+
df_out[col] = ts.dt.month.astype("int16")
|
|
141
|
+
calendar_cols.append(col)
|
|
142
|
+
elif name == "is_weekend":
|
|
143
|
+
col = "is_weekend"
|
|
144
|
+
df_out[col] = ts.dt.dayofweek.isin(WEEKEND_DAYS).astype("int8")
|
|
145
|
+
calendar_cols.append(col)
|
|
146
|
+
else: # pragma: no cover
|
|
147
|
+
# Guarded by _validate_calendar_features, but keep a defensive fallback.
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"Unsupported calendar feature {name!r}. Allowed: {sorted(ALLOWED_CALENDAR_FEATURES)}."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
feature_cols.extend(calendar_cols)
|
|
153
|
+
|
|
154
|
+
# ---------------------------------------------------------------------
|
|
155
|
+
# Optional cyclical encodings
|
|
156
|
+
# ---------------------------------------------------------------------
|
|
157
|
+
if use_cyclical_time:
|
|
158
|
+
if "hour" in calendar_cols:
|
|
159
|
+
hour = df_out["hour"].astype(float)
|
|
160
|
+
df_out["hour_sin"] = np.sin(2.0 * np.pi * hour / float(HOUR_PERIOD))
|
|
161
|
+
df_out["hour_cos"] = np.cos(2.0 * np.pi * hour / float(HOUR_PERIOD))
|
|
162
|
+
feature_cols.extend(["hour_sin", "hour_cos"])
|
|
163
|
+
|
|
164
|
+
if "dayofweek" in calendar_cols:
|
|
165
|
+
dow = df_out["dayofweek"].astype(float)
|
|
166
|
+
df_out["dow_sin"] = np.sin(2.0 * np.pi * dow / float(DOW_PERIOD))
|
|
167
|
+
df_out["dow_cos"] = np.cos(2.0 * np.pi * dow / float(DOW_PERIOD))
|
|
168
|
+
feature_cols.extend(["dow_sin", "dow_cos"])
|
|
169
|
+
|
|
170
|
+
return df_out, feature_cols, calendar_cols
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _validate_calendar_features(calendar_features: Iterable[str]) -> None:
|
|
174
|
+
r"""
|
|
175
|
+
Validate that requested calendar features are supported.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
calendar_features : Iterable[str]
|
|
180
|
+
Candidate calendar feature keys.
|
|
181
|
+
|
|
182
|
+
Raises
|
|
183
|
+
------
|
|
184
|
+
ValueError
|
|
185
|
+
If any feature key is unsupported.
|
|
186
|
+
"""
|
|
187
|
+
requested = list(calendar_features)
|
|
188
|
+
invalid = [f for f in requested if f not in ALLOWED_CALENDAR_FEATURES]
|
|
189
|
+
if invalid:
|
|
190
|
+
raise ValueError(
|
|
191
|
+
"Unsupported calendar feature(s) requested: "
|
|
192
|
+
f"{invalid}. Allowed: {sorted(ALLOWED_CALENDAR_FEATURES)}."
|
|
193
|
+
)
|