tempdisagg 0.2.5__tar.gz → 0.2.7__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.
Files changed (44) hide show
  1. tempdisagg-0.2.7/PKG-INFO +308 -0
  2. tempdisagg-0.2.7/README.md +285 -0
  3. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/pyproject.toml +3 -2
  4. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/__init__.py +14 -13
  5. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/models_handler.py +1 -44
  6. tempdisagg-0.2.7/tempdisagg/model/tempdisagg_base.py +92 -0
  7. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_core.py +22 -81
  8. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_ensemble.py +15 -71
  9. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_fitter.py +17 -17
  10. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_model.py +23 -130
  11. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_visualizer.py +18 -14
  12. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/preprocessing/disagg_input_preparer.py +16 -14
  13. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/preprocessing/timeseries_completer.py +36 -32
  14. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/utils/__init__.py +2 -0
  15. tempdisagg-0.2.7/tempdisagg/utils/retropolarizer.py +78 -0
  16. tempdisagg-0.2.7/tempdisagg.egg-info/PKG-INFO +308 -0
  17. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg.egg-info/SOURCES.txt +1 -0
  18. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg.egg-info/requires.txt +1 -0
  19. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tests/test_prediction.py +9 -0
  20. tempdisagg-0.2.5/PKG-INFO +0 -241
  21. tempdisagg-0.2.5/README.md +0 -219
  22. tempdisagg-0.2.5/tempdisagg/model/tempdisagg_base.py +0 -120
  23. tempdisagg-0.2.5/tempdisagg.egg-info/PKG-INFO +0 -241
  24. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/LICENSE +0 -0
  25. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/setup.cfg +0 -0
  26. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/core/__init__.py +0 -0
  27. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/core/numeric_utils.py +0 -0
  28. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/core/rho_optimizer.py +0 -0
  29. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/core/temporal_aggregator.py +0 -0
  30. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/__init__.py +0 -0
  31. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_adjuster.py +0 -0
  32. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/model/tempdisagg_summary.py +0 -0
  33. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/postprocessing/__init__.py +0 -0
  34. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/postprocessing/ensemble_prediction.py +0 -0
  35. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/postprocessing/post_estimation.py +0 -0
  36. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/preprocessing/__init__.py +0 -0
  37. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/preprocessing/conversion_matrix_builder.py +0 -0
  38. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/preprocessing/input_preprocessor.py +0 -0
  39. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg/utils/logging_utils.py +0 -0
  40. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg.egg-info/dependency_links.txt +0 -0
  41. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tempdisagg.egg-info/top_level.txt +0 -0
  42. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tests/test_numeric_utils.py +0 -0
  43. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tests/test_rho_optimizer.py +0 -0
  44. {tempdisagg-0.2.5 → tempdisagg-0.2.7}/tests/test_summary_visualize.py +0 -0
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: tempdisagg
3
+ Version: 0.2.7
4
+ Summary: Temporal disaggregation models in Python
5
+ Author-email: Jaime Vera-Jaramillo <jaimevera1107@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jaimevera1107/tempdisagg
8
+ Keywords: temporal disaggregation,time series,econometrics,interpolation
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy>=1.21
18
+ Requires-Dist: pandas>=1.3
19
+ Requires-Dist: scipy>=1.7
20
+ Requires-Dist: matplotlib>=3.4
21
+ Requires-Dist: scikit-learn<2.0,>=1.6
22
+ Dynamic: license-file
23
+
24
+ # ⚡️ **tempdisagg**
25
+
26
+ >### **Temporal Disaggregation Models in Python**
27
+
28
+ *High-Frequency Estimation from Low-Frequency Data — Modular · Robust · Ready for Production*
29
+
30
+ ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
31
+ ![Python](https://img.shields.io/badge/Python-3.8%2B-blue)
32
+ ![Status](https://img.shields.io/badge/build-passing-brightgreen)
33
+ ![Coverage](https://img.shields.io/badge/tests-100%25-success)
34
+ ![PyPI](https://img.shields.io/pypi/v/tempdisagg)
35
+
36
+ ---
37
+
38
+ `tempdisagg` is a production-ready Python library for **temporal disaggregation of time series** — transforming low-frequency data into high-frequency estimates while preserving consistency.
39
+
40
+ > It supports all major classical methods — **Chow-Lin**, **Litterman**, **Denton**, **Fernández**, **Uniform** — and provides a **clean modular architecture** inspired by R's `tempdisagg`, with modern additions:
41
+
42
+ - 📈 Regression + autoregressive adjustment
43
+ - 📉 Differencing & smoothing interpolators
44
+ - 🤖 Ensemble prediction engine
45
+ - 🧠 Intelligent padding & interpolation
46
+ - 🔧 Post-estimation fix for negative values
47
+ - 🔄 Optional retropolarization via regression
48
+
49
+ ---
50
+
51
+ ## 🔍 Why Temporal Disaggregation?
52
+
53
+ Official indicators often come in low frequency (e.g. yearly GDP), while economic analysis or forecasting needs monthly or quarterly granularity. `tempdisagg` fills this gap using consistent econometric techniques to create **granular estimates** that **respect original aggregates**.
54
+
55
+ ---
56
+
57
+ ## 📚 Methods Implemented
58
+
59
+ | Method(s) | Description |
60
+ |-------------------------------------------------------------------------|---------------------------------------------------------------|
61
+ | `ols` | Ordinary Least Squares (baseline) |
62
+ | `denton`, `denton-opt` | Denton interpolation with differencing |
63
+ | `denton-colette` | Cholette smoother variant from Dagum & Cholette |
64
+ | `chow-lin`, `chow-lin-opt`, `chow-lin-ecotrim`, `chow-lin-quilis` | Regression + AR(1) residual modeling |
65
+ | `litterman`, `litterman-opt` | Random walk / AR(1) prior models |
66
+ | `fernandez` | Fixed-ρ Litterman (ρ = 0) |
67
+ | `fast` | Fast approximation of Denton-Cholette |
68
+ | `uniform` | Even distribution across subperiods |
69
+
70
+ ---
71
+
72
+ ## 💾 Installation
73
+
74
+ ```bash
75
+ pip install tempdisagg
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 🚀 Quick Example
81
+
82
+ ```python
83
+ from tempdisagg import TempDisaggModel
84
+ import pandas as pd
85
+ import numpy as np
86
+
87
+ # Sample input data (monthly disaggregation of yearly total)
88
+ df = pd.DataFrame({
89
+ "Index": [2020]*12 + [2021]*12,
90
+ "Grain": list(range(1, 13)) * 2,
91
+ "y": [1200] + [np.nan]*11 + [1500] + [np.nan]*11,
92
+ "X": np.linspace(100, 200, 24)
93
+ })
94
+
95
+ # Fit model
96
+ model = TempDisaggModel(method="chow-lin-opt", conversion="sum")
97
+ model.fit(df)
98
+
99
+ # Predict high-frequency series
100
+ y_hat = model.predict()
101
+
102
+ # Adjust negatives (if any; OPTIONAL)
103
+ y_adj = model.adjust_output()
104
+
105
+ # Show results
106
+ model.summary()
107
+ model.plot()
108
+ ````
109
+
110
+ ---
111
+
112
+ ## ⚡ Example with Real Data
113
+
114
+ ```python
115
+ import statsmodels.api as sm
116
+ from tempdisagg import TempDisaggModel
117
+
118
+ # Load macroeconomic dataset (quarterly)
119
+ macro = sm.datasets.macrodata.load_pandas().data
120
+ macro["Index"] = macro["year"].astype(int)
121
+ macro["Grain"] = macro["quarter"].astype(int)
122
+ macro["X"] = macro["realcons"]
123
+
124
+ # Aggregate GDP to annual level
125
+ gdp_annual = macro.groupby("Index")["realgdp"].mean().reset_index()
126
+ gdp_annual.columns = ["Index", "y"]
127
+
128
+ # Merge back into full frame
129
+ df = macro.merge(gdp_annual, on="Index", how="left")[["Index", "Grain", "y", "X"]]
130
+
131
+ # Fit model and predict
132
+ model = TempDisaggModel(method="chow-lin-opt", conversion="average")
133
+ model.fit(df)
134
+
135
+ # Get high-frequency estimates
136
+ y_hat = model.predict(full=False)
137
+
138
+ # Optional: post-estimation adjustment
139
+ y_adj = model.adjust_output(full=False)
140
+
141
+ # Summary and plot
142
+ model.summary()
143
+ model.plot()
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 🤖 Ensemble Prediction
149
+
150
+ Run all models and let the library **find the optimal weighted combination**.
151
+
152
+ ```python
153
+ model = TempDisaggModel(method="ensemble", conversion="sum")
154
+ model.fit(df)
155
+
156
+ model.summary()
157
+ model.plot()
158
+ ```
159
+
160
+ Behind the scenes:
161
+ - Each method is fitted separately.
162
+ - Error metrics (e.g. MAE) are computed.
163
+ - Weights are optimized to minimize global error.
164
+ - Final prediction is a weighted average across models.
165
+
166
+ ---
167
+
168
+ ## 🚫 Negative Value Adjustment
169
+
170
+ When disaggregation outputs negatives (due to smoothing or regression noise), `tempdisagg` can correct them **without violating consistency**.
171
+
172
+ ```python
173
+ model.fit(df)
174
+ y_hat = model.adjust_output()
175
+ ```
176
+
177
+ Internally:
178
+ - Detects negatives in each group.
179
+ - Redistributes values proportionally.
180
+ - Ensures aggregate values match original data.
181
+
182
+ ---
183
+
184
+ ## 🧠 Retropolarizer: Smart Interpolation
185
+
186
+ For missing values in the target (`y`), you can activate the **Retropolarizer**: a module that imputes via regression, proportions, or exponential smoothing.
187
+
188
+ ```python
189
+ from tempdisagg import Retropolarizer
190
+
191
+ retro = Retropolarizer(method="linear_regression")
192
+ df["y_imputed"] = retro.fit_transform(df, target_col="y", aux_col="X")
193
+ ```
194
+
195
+ Or use it inside any model:
196
+
197
+ ```python
198
+ model = TempDisaggModel(
199
+ method="chow-lin",
200
+ use_retropolarizer=True,
201
+ retro_method="linear_regression"
202
+ )
203
+ model.fit(df)
204
+ ```
205
+
206
+ Available methods:
207
+
208
+ - 'proportion'
209
+ - 'linear_regression'
210
+ - 'polynomial_regression'
211
+ - 'exponential_smoothing'
212
+ - 'mlp_regression'
213
+
214
+ > **Note:** The Retropolarizer is only used to impute missing values in the `y` column. It is **not** intended for interpolating the `X` (indicator) variable.
215
+
216
+
217
+ ---
218
+
219
+ ## 📘 Input Format
220
+
221
+ Your data must be in long format:
222
+
223
+ | Column | Meaning |
224
+ |----------|------------------------------------------------|
225
+ | `Index` | Low-frequency group ID (e.g., year) |
226
+ | `Grain` | High-frequency unit (e.g., month number) |
227
+ | `y` | Target variable (repeated within group) |
228
+ | `X` | Indicator variable at high frequency |
229
+
230
+ ```text
231
+ Index | Grain | y | X
232
+ ------|-------|-------|-----
233
+ 2020 | 1 | 1000 | 10.1
234
+ 2020 | 2 | 1000 | 11.3
235
+ 2020 | 3 | 1000 | 12.5
236
+ ... | ... | ... | ...
237
+ ```
238
+
239
+ ---
240
+
241
+ ## 🧩 Modular Design
242
+
243
+ | Component | Role |
244
+ |------------------------|--------------------------------------------|
245
+ | `TempDisaggModel` | High-level interface |
246
+ | `DisaggInputPreparer` | Input validation + padding + interpolation |
247
+ | `ModelsHandler` | Implements disaggregation methods |
248
+ | `RhoOptimizer` | Optimizes AR(1) parameter |
249
+ | `PostEstimation` | Adjusts negative values |
250
+ | `EnsemblePrediction` | Combines multiple models |
251
+ | `Retropolarizer` | Regression-based imputer for `y` |
252
+
253
+ ---
254
+
255
+ ## 🧪 Testing & Reliability
256
+
257
+ - ✅ Full test coverage
258
+ - ✅ Input validation & fallbacks
259
+ - ✅ Padding & missing data supported
260
+ - ✅ Consistency validation `C @ y_hat ≈ y_l`
261
+
262
+ ---
263
+
264
+ ## 🔍 API Overview
265
+
266
+ | Method | Description |
267
+ |--------------------------------|-----------------------------------------------------|
268
+ | `.fit(df)` | Fit the model |
269
+ | `.predict(full=True)` | Predict disaggregated values |
270
+ | `.adjust_output(full=True)` | Fix negative predictions |
271
+ | `.summary(metric="mae")` | Print coefficients, rho, and errors |
272
+ | `.plot(use_adjusted=False)` | Visualize predictions |
273
+ | `.get_params()` / `.set_params()` | Get/set model config |
274
+ | `.to_dict()` | Export results |
275
+
276
+ ---
277
+
278
+ ## 📦 Dependencies
279
+
280
+ `tempdisagg` relies on the following Python libraries:
281
+
282
+ - `pandas` – data manipulation
283
+ - `numpy` – numerical operations
284
+ - `matplotlib` – plotting
285
+ - `scipy` and `statsmodels` – regression and optimization
286
+ - `scikit-learn` – used in `Retropolarizer` (e.g., MLP imputation)
287
+
288
+ > These packages are automatically installed with `pip install tempdisagg`.
289
+
290
+ ---
291
+
292
+ ## 📚 References
293
+
294
+ - Dagum & Cholette (2006), *Benchmarking, Temporal Distribution, and Reconciliation Methods*
295
+ - Denton (1971), *Adjustment of Monthly or Quarterly Series*
296
+ - Chow & Lin (1971), *Best Linear Unbiased Estimation of Missing Observations*
297
+ - Fernández (1981), *Methodological Note on a Monthly Indicator*
298
+ - Litterman (1983), *A Random Walk, Markov Model for Forecasting*
299
+ - tempdisagg (R package)
300
+
301
+ ---
302
+
303
+ ## 📃 License
304
+
305
+ MIT License — See [LICENSE](./LICENSE) for details.
306
+
307
+
308
+ Developed and maintained by Jaime Vera-Jaramillo — Contributions are welcome ❤️.
@@ -0,0 +1,285 @@
1
+ # ⚡️ **tempdisagg**
2
+
3
+ >### **Temporal Disaggregation Models in Python**
4
+
5
+ *High-Frequency Estimation from Low-Frequency Data — Modular · Robust · Ready for Production*
6
+
7
+ ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
8
+ ![Python](https://img.shields.io/badge/Python-3.8%2B-blue)
9
+ ![Status](https://img.shields.io/badge/build-passing-brightgreen)
10
+ ![Coverage](https://img.shields.io/badge/tests-100%25-success)
11
+ ![PyPI](https://img.shields.io/pypi/v/tempdisagg)
12
+
13
+ ---
14
+
15
+ `tempdisagg` is a production-ready Python library for **temporal disaggregation of time series** — transforming low-frequency data into high-frequency estimates while preserving consistency.
16
+
17
+ > It supports all major classical methods — **Chow-Lin**, **Litterman**, **Denton**, **Fernández**, **Uniform** — and provides a **clean modular architecture** inspired by R's `tempdisagg`, with modern additions:
18
+
19
+ - 📈 Regression + autoregressive adjustment
20
+ - 📉 Differencing & smoothing interpolators
21
+ - 🤖 Ensemble prediction engine
22
+ - 🧠 Intelligent padding & interpolation
23
+ - 🔧 Post-estimation fix for negative values
24
+ - 🔄 Optional retropolarization via regression
25
+
26
+ ---
27
+
28
+ ## 🔍 Why Temporal Disaggregation?
29
+
30
+ Official indicators often come in low frequency (e.g. yearly GDP), while economic analysis or forecasting needs monthly or quarterly granularity. `tempdisagg` fills this gap using consistent econometric techniques to create **granular estimates** that **respect original aggregates**.
31
+
32
+ ---
33
+
34
+ ## 📚 Methods Implemented
35
+
36
+ | Method(s) | Description |
37
+ |-------------------------------------------------------------------------|---------------------------------------------------------------|
38
+ | `ols` | Ordinary Least Squares (baseline) |
39
+ | `denton`, `denton-opt` | Denton interpolation with differencing |
40
+ | `denton-colette` | Cholette smoother variant from Dagum & Cholette |
41
+ | `chow-lin`, `chow-lin-opt`, `chow-lin-ecotrim`, `chow-lin-quilis` | Regression + AR(1) residual modeling |
42
+ | `litterman`, `litterman-opt` | Random walk / AR(1) prior models |
43
+ | `fernandez` | Fixed-ρ Litterman (ρ = 0) |
44
+ | `fast` | Fast approximation of Denton-Cholette |
45
+ | `uniform` | Even distribution across subperiods |
46
+
47
+ ---
48
+
49
+ ## 💾 Installation
50
+
51
+ ```bash
52
+ pip install tempdisagg
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 🚀 Quick Example
58
+
59
+ ```python
60
+ from tempdisagg import TempDisaggModel
61
+ import pandas as pd
62
+ import numpy as np
63
+
64
+ # Sample input data (monthly disaggregation of yearly total)
65
+ df = pd.DataFrame({
66
+ "Index": [2020]*12 + [2021]*12,
67
+ "Grain": list(range(1, 13)) * 2,
68
+ "y": [1200] + [np.nan]*11 + [1500] + [np.nan]*11,
69
+ "X": np.linspace(100, 200, 24)
70
+ })
71
+
72
+ # Fit model
73
+ model = TempDisaggModel(method="chow-lin-opt", conversion="sum")
74
+ model.fit(df)
75
+
76
+ # Predict high-frequency series
77
+ y_hat = model.predict()
78
+
79
+ # Adjust negatives (if any; OPTIONAL)
80
+ y_adj = model.adjust_output()
81
+
82
+ # Show results
83
+ model.summary()
84
+ model.plot()
85
+ ````
86
+
87
+ ---
88
+
89
+ ## ⚡ Example with Real Data
90
+
91
+ ```python
92
+ import statsmodels.api as sm
93
+ from tempdisagg import TempDisaggModel
94
+
95
+ # Load macroeconomic dataset (quarterly)
96
+ macro = sm.datasets.macrodata.load_pandas().data
97
+ macro["Index"] = macro["year"].astype(int)
98
+ macro["Grain"] = macro["quarter"].astype(int)
99
+ macro["X"] = macro["realcons"]
100
+
101
+ # Aggregate GDP to annual level
102
+ gdp_annual = macro.groupby("Index")["realgdp"].mean().reset_index()
103
+ gdp_annual.columns = ["Index", "y"]
104
+
105
+ # Merge back into full frame
106
+ df = macro.merge(gdp_annual, on="Index", how="left")[["Index", "Grain", "y", "X"]]
107
+
108
+ # Fit model and predict
109
+ model = TempDisaggModel(method="chow-lin-opt", conversion="average")
110
+ model.fit(df)
111
+
112
+ # Get high-frequency estimates
113
+ y_hat = model.predict(full=False)
114
+
115
+ # Optional: post-estimation adjustment
116
+ y_adj = model.adjust_output(full=False)
117
+
118
+ # Summary and plot
119
+ model.summary()
120
+ model.plot()
121
+ ```
122
+
123
+ ---
124
+
125
+ ## 🤖 Ensemble Prediction
126
+
127
+ Run all models and let the library **find the optimal weighted combination**.
128
+
129
+ ```python
130
+ model = TempDisaggModel(method="ensemble", conversion="sum")
131
+ model.fit(df)
132
+
133
+ model.summary()
134
+ model.plot()
135
+ ```
136
+
137
+ Behind the scenes:
138
+ - Each method is fitted separately.
139
+ - Error metrics (e.g. MAE) are computed.
140
+ - Weights are optimized to minimize global error.
141
+ - Final prediction is a weighted average across models.
142
+
143
+ ---
144
+
145
+ ## 🚫 Negative Value Adjustment
146
+
147
+ When disaggregation outputs negatives (due to smoothing or regression noise), `tempdisagg` can correct them **without violating consistency**.
148
+
149
+ ```python
150
+ model.fit(df)
151
+ y_hat = model.adjust_output()
152
+ ```
153
+
154
+ Internally:
155
+ - Detects negatives in each group.
156
+ - Redistributes values proportionally.
157
+ - Ensures aggregate values match original data.
158
+
159
+ ---
160
+
161
+ ## 🧠 Retropolarizer: Smart Interpolation
162
+
163
+ For missing values in the target (`y`), you can activate the **Retropolarizer**: a module that imputes via regression, proportions, or exponential smoothing.
164
+
165
+ ```python
166
+ from tempdisagg import Retropolarizer
167
+
168
+ retro = Retropolarizer(method="linear_regression")
169
+ df["y_imputed"] = retro.fit_transform(df, target_col="y", aux_col="X")
170
+ ```
171
+
172
+ Or use it inside any model:
173
+
174
+ ```python
175
+ model = TempDisaggModel(
176
+ method="chow-lin",
177
+ use_retropolarizer=True,
178
+ retro_method="linear_regression"
179
+ )
180
+ model.fit(df)
181
+ ```
182
+
183
+ Available methods:
184
+
185
+ - 'proportion'
186
+ - 'linear_regression'
187
+ - 'polynomial_regression'
188
+ - 'exponential_smoothing'
189
+ - 'mlp_regression'
190
+
191
+ > **Note:** The Retropolarizer is only used to impute missing values in the `y` column. It is **not** intended for interpolating the `X` (indicator) variable.
192
+
193
+
194
+ ---
195
+
196
+ ## 📘 Input Format
197
+
198
+ Your data must be in long format:
199
+
200
+ | Column | Meaning |
201
+ |----------|------------------------------------------------|
202
+ | `Index` | Low-frequency group ID (e.g., year) |
203
+ | `Grain` | High-frequency unit (e.g., month number) |
204
+ | `y` | Target variable (repeated within group) |
205
+ | `X` | Indicator variable at high frequency |
206
+
207
+ ```text
208
+ Index | Grain | y | X
209
+ ------|-------|-------|-----
210
+ 2020 | 1 | 1000 | 10.1
211
+ 2020 | 2 | 1000 | 11.3
212
+ 2020 | 3 | 1000 | 12.5
213
+ ... | ... | ... | ...
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 🧩 Modular Design
219
+
220
+ | Component | Role |
221
+ |------------------------|--------------------------------------------|
222
+ | `TempDisaggModel` | High-level interface |
223
+ | `DisaggInputPreparer` | Input validation + padding + interpolation |
224
+ | `ModelsHandler` | Implements disaggregation methods |
225
+ | `RhoOptimizer` | Optimizes AR(1) parameter |
226
+ | `PostEstimation` | Adjusts negative values |
227
+ | `EnsemblePrediction` | Combines multiple models |
228
+ | `Retropolarizer` | Regression-based imputer for `y` |
229
+
230
+ ---
231
+
232
+ ## 🧪 Testing & Reliability
233
+
234
+ - ✅ Full test coverage
235
+ - ✅ Input validation & fallbacks
236
+ - ✅ Padding & missing data supported
237
+ - ✅ Consistency validation `C @ y_hat ≈ y_l`
238
+
239
+ ---
240
+
241
+ ## 🔍 API Overview
242
+
243
+ | Method | Description |
244
+ |--------------------------------|-----------------------------------------------------|
245
+ | `.fit(df)` | Fit the model |
246
+ | `.predict(full=True)` | Predict disaggregated values |
247
+ | `.adjust_output(full=True)` | Fix negative predictions |
248
+ | `.summary(metric="mae")` | Print coefficients, rho, and errors |
249
+ | `.plot(use_adjusted=False)` | Visualize predictions |
250
+ | `.get_params()` / `.set_params()` | Get/set model config |
251
+ | `.to_dict()` | Export results |
252
+
253
+ ---
254
+
255
+ ## 📦 Dependencies
256
+
257
+ `tempdisagg` relies on the following Python libraries:
258
+
259
+ - `pandas` – data manipulation
260
+ - `numpy` – numerical operations
261
+ - `matplotlib` – plotting
262
+ - `scipy` and `statsmodels` – regression and optimization
263
+ - `scikit-learn` – used in `Retropolarizer` (e.g., MLP imputation)
264
+
265
+ > These packages are automatically installed with `pip install tempdisagg`.
266
+
267
+ ---
268
+
269
+ ## 📚 References
270
+
271
+ - Dagum & Cholette (2006), *Benchmarking, Temporal Distribution, and Reconciliation Methods*
272
+ - Denton (1971), *Adjustment of Monthly or Quarterly Series*
273
+ - Chow & Lin (1971), *Best Linear Unbiased Estimation of Missing Observations*
274
+ - Fernández (1981), *Methodological Note on a Monthly Indicator*
275
+ - Litterman (1983), *A Random Walk, Markov Model for Forecasting*
276
+ - tempdisagg (R package)
277
+
278
+ ---
279
+
280
+ ## 📃 License
281
+
282
+ MIT License — See [LICENSE](./LICENSE) for details.
283
+
284
+
285
+ Developed and maintained by Jaime Vera-Jaramillo — Contributions are welcome ❤️.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tempdisagg"
7
- version = "0.2.5"
7
+ version = "0.2.7"
8
8
  description = "Temporal disaggregation models in Python"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -25,7 +25,8 @@ dependencies = [
25
25
  "numpy>=1.21",
26
26
  "pandas>=1.3",
27
27
  "scipy>=1.7",
28
- "matplotlib>=3.4"
28
+ "matplotlib>=3.4",
29
+ "scikit-learn>=1.6,<2.0"
29
30
  ]
30
31
 
31
32
  [tool.setuptools.packages.find]
@@ -1,30 +1,31 @@
1
- # tempdisagg/__init__.py
2
-
3
1
  """
4
2
  tempdisagg: Temporal disaggregation of low-frequency time series using various statistical methods.
5
3
  """
6
4
 
7
5
  # Public API
8
6
  from .model.tempdisagg_model import TempDisaggModel
7
+ from .utils.retropolarizer import Retropolarizer
8
+ from .core.temporal_aggregator import TemporalAggregator
9
9
 
10
10
  # Define what gets imported with `from tempdisagg import *`
11
11
  __all__ = [
12
- "TempDisaggModel",
13
- "ModelFitter",
14
- "EnsemblePredictor",
15
- "TempDisaggVisualizer",
16
- "TempDisaggReporter",
17
- "TempDisaggAdjuster",
12
+ "ConversionMatrixBuilder",
18
13
  "DisaggInputPreparer",
14
+ "EnsemblePrediction",
15
+ "EnsemblePredictor",
19
16
  "InputPreprocessor",
20
- "TimeSeriesCompleter",
21
- "ConversionMatrixBuilder",
22
17
  "ModelsHandler",
23
- "RhoOptimizer",
18
+ "ModelFitter",
24
19
  "NumericUtils",
25
20
  "PostEstimation",
26
- "EnsemblePrediction",
21
+ "Retropolarizer",
22
+ "RhoOptimizer",
23
+ "TempDisaggAdjuster",
24
+ "TempDisaggModel",
25
+ "TempDisaggReporter",
26
+ "TempDisaggVisualizer",
27
27
  "TemporalAggregator",
28
+ "TimeSeriesCompleter",
28
29
  ]
29
30
 
30
- __version__= "0.2.5"
31
+ __version__ = "0.2.7"