dfm-python 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
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.
- dfm_python/__init__.py +2 -2
- dfm_python/{dfm_api.py → api.py} +41 -251
- dfm_python/config.py +72 -7
- dfm_python/core/__init__.py +59 -0
- dfm_python/core/diagnostics.py +274 -0
- dfm_python/core/em.py +1022 -0
- dfm_python/core/grouping.py +54 -0
- dfm_python/core/helpers.py +56 -0
- dfm_python/core/numeric.py +346 -0
- dfm_python/core/results.py +70 -0
- dfm_python/dfm.py +497 -3538
- dfm_python/kalman.py +18 -0
- dfm_python/utils/data_utils.py +3 -5
- dfm_python-0.2.2.dist-info/METADATA +312 -0
- dfm_python-0.2.2.dist-info/RECORD +21 -0
- dfm_python-0.2.0.dist-info/METADATA +0 -647
- dfm_python-0.2.0.dist-info/RECORD +0 -14
- {dfm_python-0.2.0.dist-info → dfm_python-0.2.2.dist-info}/WHEEL +0 -0
- {dfm_python-0.2.0.dist-info → dfm_python-0.2.2.dist-info}/licenses/LICENSE +0 -0
dfm_python/kalman.py
CHANGED
|
@@ -155,10 +155,28 @@ def skf(Y: np.ndarray, A: np.ndarray, C: np.ndarray, Q: np.ndarray,
|
|
|
155
155
|
Zu = Z_0.copy() # Z_0|0 (In loop, Zu gives Z_t | t)
|
|
156
156
|
Vu = V_0.copy() # V_0|0 (In loop, Vu gives V_t | t)
|
|
157
157
|
|
|
158
|
+
# Validate dimensions match
|
|
159
|
+
if Zu.shape[0] != m:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Dimension mismatch: Z_0 has shape {Zu.shape[0]}, but C has {m} columns. "
|
|
162
|
+
f"This usually indicates a mismatch between init_conditions and em_step. "
|
|
163
|
+
f"Z_0 should have dimension {m} to match C.shape[1]."
|
|
164
|
+
)
|
|
165
|
+
if Vu.shape[0] != m or Vu.shape[1] != m:
|
|
166
|
+
raise ValueError(
|
|
167
|
+
f"Dimension mismatch: V_0 has shape {Vu.shape}, but expected ({m}, {m}). "
|
|
168
|
+
f"This usually indicates a mismatch between init_conditions and em_step."
|
|
169
|
+
)
|
|
170
|
+
|
|
158
171
|
# Store initial values
|
|
159
172
|
ZmU[:, 0] = Zu
|
|
160
173
|
VmU[:, :, 0] = Vu
|
|
161
174
|
|
|
175
|
+
# Initialize variables for final iteration (used after loop)
|
|
176
|
+
Y_t = np.array([]) # Initialize Y_t to empty array
|
|
177
|
+
C_t = None
|
|
178
|
+
VCF = None
|
|
179
|
+
|
|
162
180
|
# Kalman filter procedure
|
|
163
181
|
for t in range(nobs):
|
|
164
182
|
# Calculate prior distribution
|
dfm_python/utils/data_utils.py
CHANGED
|
@@ -130,12 +130,10 @@ def summarize(X: np.ndarray, Time, config, vintage: Optional[str] = None) -> Non
|
|
|
130
130
|
else:
|
|
131
131
|
series_names = []
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
from ..core.helpers import safe_get_method
|
|
134
|
+
series_ids = safe_get_method(config, 'get_series_ids', [])
|
|
135
|
+
if not series_ids and hasattr(config, 'SeriesID'):
|
|
136
136
|
series_ids = config.SeriesID
|
|
137
|
-
else:
|
|
138
|
-
series_ids = []
|
|
139
137
|
|
|
140
138
|
if hasattr(config, 'get_frequencies'):
|
|
141
139
|
frequencies = config.get_frequencies()
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dfm-python
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Dynamic Factor Model (DFM) estimation and nowcasting in Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/yourusername/dfm-python
|
|
6
|
+
Project-URL: Documentation, https://github.com/yourusername/dfm-python#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/yourusername/dfm-python
|
|
8
|
+
Project-URL: Issues, https://github.com/yourusername/dfm-python/issues
|
|
9
|
+
Author: DFM Python Contributors
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: dfm,dynamic-factor-model,econometrics,forecasting,nowcasting,time-series
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: hydra-core>=1.3.2
|
|
23
|
+
Requires-Dist: matplotlib>=3.10.7
|
|
24
|
+
Requires-Dist: numpy>=1.24.0
|
|
25
|
+
Requires-Dist: pandas>=2.0.0
|
|
26
|
+
Requires-Dist: scipy>=1.10.0
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: httpx>=0.24.0; extra == 'all'
|
|
29
|
+
Requires-Dist: hydra-core>=1.3.0; extra == 'all'
|
|
30
|
+
Requires-Dist: omegaconf>=2.3.0; extra == 'all'
|
|
31
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
|
|
32
|
+
Requires-Dist: pydantic-settings>=2.11.0; extra == 'all'
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == 'all'
|
|
34
|
+
Requires-Dist: supabase>=2.0.0; extra == 'all'
|
|
35
|
+
Provides-Extra: database
|
|
36
|
+
Requires-Dist: httpx>=0.24.0; extra == 'database'
|
|
37
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'database'
|
|
38
|
+
Requires-Dist: pydantic-settings>=2.11.0; extra == 'database'
|
|
39
|
+
Requires-Dist: supabase>=2.0.0; extra == 'database'
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
42
|
+
Provides-Extra: hydra
|
|
43
|
+
Requires-Dist: hydra-core>=1.3.0; extra == 'hydra'
|
|
44
|
+
Requires-Dist: omegaconf>=2.3.0; extra == 'hydra'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# dfm-python: Dynamic Factor Models for Python
|
|
48
|
+
|
|
49
|
+
[](https://pypi.org/project/dfm-python/)
|
|
50
|
+
[](https://www.python.org/downloads/)
|
|
51
|
+
|
|
52
|
+
A Python implementation of **Dynamic Factor Models (DFM)** for nowcasting and forecasting high-dimensional time series. Implements clock-based synchronization and tent kernel aggregation for mixed-frequency data.
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **Mixed-frequency data**: Monthly, quarterly, semi-annual, annual
|
|
57
|
+
- **Clock-based framework**: All factors evolve at a common clock frequency
|
|
58
|
+
- **Block structure**: Flexible factor organization (global, sector-specific)
|
|
59
|
+
- **Robust missing data**: Spline interpolation and Kalman filter handling
|
|
60
|
+
- **News decomposition**: Attribute forecast changes to data releases
|
|
61
|
+
- **Generic design**: YAML configs or direct object creation, extensible via adapters
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install dfm-python
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Requirements**: Python >= 3.10, numpy >= 1.24.0, pandas >= 2.0.0, scipy >= 1.10.0
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### Module-Level API (Recommended)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import dfm_python as dfm
|
|
77
|
+
from dfm_python.config import Params
|
|
78
|
+
|
|
79
|
+
# 1. Load config from spec CSV + Params
|
|
80
|
+
params = Params(max_iter=5000, threshold=1e-5)
|
|
81
|
+
dfm.from_spec('data/sample_spec.csv', params=params)
|
|
82
|
+
|
|
83
|
+
# 2. Load data
|
|
84
|
+
dfm.load_data('data/sample_data.csv', sample_start='2021-01-01', sample_end='2022-12-31')
|
|
85
|
+
|
|
86
|
+
# 3. Train
|
|
87
|
+
dfm.train(max_iter=5000)
|
|
88
|
+
|
|
89
|
+
# 4. Forecast
|
|
90
|
+
X_forecast, Z_forecast = dfm.predict(horizon=12)
|
|
91
|
+
|
|
92
|
+
# 5. Plot
|
|
93
|
+
dfm.plot(kind='factor', factor_index=0, forecast_horizon=12, save_path='outputs/factor.png')
|
|
94
|
+
|
|
95
|
+
# 6. Access results
|
|
96
|
+
result = dfm.get_result()
|
|
97
|
+
factors = result.Z # (T × m) Smoothed factors
|
|
98
|
+
loadings = result.C # (N × m) Factor loadings
|
|
99
|
+
smoothed = result.X_sm # (T × N) Smoothed data
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Alternative: YAML Configuration
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
import dfm_python as dfm
|
|
106
|
+
|
|
107
|
+
# Load from YAML
|
|
108
|
+
dfm.from_yaml('config/default.yaml')
|
|
109
|
+
dfm.load_data('data/sample_data.csv')
|
|
110
|
+
dfm.train()
|
|
111
|
+
X_forecast, Z_forecast = dfm.predict(horizon=12)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Alternative: Direct Class Usage
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from dfm_python import DFM, DFMConfig, SeriesConfig, BlockConfig
|
|
118
|
+
|
|
119
|
+
# Create config
|
|
120
|
+
config = DFMConfig(
|
|
121
|
+
series=[SeriesConfig(frequency='m', transformation='lin', blocks=[1], series_id='s1')],
|
|
122
|
+
blocks={'Block_Global': BlockConfig(factors=1, clock='m')}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Fit model
|
|
126
|
+
model = DFM()
|
|
127
|
+
result = model.fit(X, config, max_iter=100)
|
|
128
|
+
factors = result.Z
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
### Spec CSV + Params (Recommended for CSV workflows)
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from dfm_python.config import Params
|
|
137
|
+
|
|
138
|
+
params = Params(
|
|
139
|
+
max_iter=5000,
|
|
140
|
+
threshold=1e-5,
|
|
141
|
+
regularization_scale=1e-5,
|
|
142
|
+
damping_factor=0.8
|
|
143
|
+
)
|
|
144
|
+
dfm.from_spec('data/sample_spec.csv', params=params)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Hydra Decorator (Recommended for Hydra users)
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import hydra
|
|
151
|
+
from hydra.utils import get_original_cwd
|
|
152
|
+
from omegaconf import DictConfig
|
|
153
|
+
import dfm_python as dfm
|
|
154
|
+
|
|
155
|
+
@hydra.main(config_path="../config", config_name="default", version_base="1.3")
|
|
156
|
+
def main(cfg: DictConfig) -> None:
|
|
157
|
+
dfm.load_config(hydra=cfg)
|
|
158
|
+
dfm.load_data(str(get_original_cwd() / "data" / "sample_data.csv"))
|
|
159
|
+
dfm.train(max_iter=cfg.max_iter)
|
|
160
|
+
X_forecast, Z_forecast = dfm.predict(horizon=cfg.get('forecast_horizon', 12))
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**CLI Overrides**: `python script.py max_iter=10 threshold=1e-4 blocks.Block_Global.factors=2`
|
|
164
|
+
|
|
165
|
+
### Dictionary
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
config_dict = {
|
|
169
|
+
'clock': 'm',
|
|
170
|
+
'max_iter': 5000,
|
|
171
|
+
'blocks': {'Block_Global': {'factors': 1, 'clock': 'm'}},
|
|
172
|
+
'series': [{'series_id': 's1', 'frequency': 'm', 'transformation': 'lin', 'blocks': [0]}]
|
|
173
|
+
}
|
|
174
|
+
dfm.from_dict(config_dict)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Key Parameters
|
|
178
|
+
|
|
179
|
+
- **clock**: Base frequency for latent factors (typically "m" for monthly)
|
|
180
|
+
- **threshold**: EM convergence criterion (default: 1e-5)
|
|
181
|
+
- **max_iter**: Maximum EM iterations (default: 5000)
|
|
182
|
+
- **ar_lag**: Autoregressive lag for factors (default: 1)
|
|
183
|
+
- **regularization_scale**: Scale factor for ridge regularization (default: 1e-5)
|
|
184
|
+
- **damping_factor**: Damping factor for parameter updates (default: 0.8)
|
|
185
|
+
|
|
186
|
+
All numerical stability parameters are configurable and transparent. See `Params` dataclass for full list.
|
|
187
|
+
|
|
188
|
+
## Data Format
|
|
189
|
+
|
|
190
|
+
CSV file with series as columns and dates as rows:
|
|
191
|
+
|
|
192
|
+
```csv
|
|
193
|
+
Date,gdp_real,consumption,investment
|
|
194
|
+
2000-01-01,,98.5,95.0
|
|
195
|
+
2000-02-01,,98.7,95.2
|
|
196
|
+
2000-03-01,100.5,99.0,95.5
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Requirements**:
|
|
200
|
+
- First column: `Date` (YYYY-MM-DD format)
|
|
201
|
+
- Column names: Must match `series_id` in configuration
|
|
202
|
+
- Missing values: Empty cells or NaN
|
|
203
|
+
- Mixed frequencies: Quarterly series only at quarter-end months
|
|
204
|
+
|
|
205
|
+
**Frequency Support**: Monthly (m), Quarterly (q), Semi-annual (sa), Annual (a)
|
|
206
|
+
|
|
207
|
+
## News Decomposition
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from dfm_python import news_dfm
|
|
211
|
+
|
|
212
|
+
# Decompose forecast updates
|
|
213
|
+
y_old, y_new, singlenews, actual, forecast, weight, t_miss, v_miss, innov = news_dfm(
|
|
214
|
+
X_old, result_old, t_fcst=100, v_news=0
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Forecast update
|
|
218
|
+
forecast_update = y_new - y_old
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## API Reference
|
|
222
|
+
|
|
223
|
+
### Module-Level Functions
|
|
224
|
+
|
|
225
|
+
- `dfm.from_spec(spec_path, params=None)` - Load from spec CSV + Params
|
|
226
|
+
- `dfm.from_yaml(yaml_path)` - Load from YAML file
|
|
227
|
+
- `dfm.from_dict(config_dict)` - Load from dictionary
|
|
228
|
+
- `dfm.load_data(data_path, sample_start=None, sample_end=None)` - Load data
|
|
229
|
+
- `dfm.train(max_iter=None, threshold=None, **kwargs)` - Train model
|
|
230
|
+
- `dfm.predict(horizon=12)` - Forecast series and factors
|
|
231
|
+
- `dfm.plot(kind='factor', factor_index=0, forecast_horizon=None, save_path=None)` - Plot results
|
|
232
|
+
- `dfm.get_result()` - Get `DFMResult` object
|
|
233
|
+
|
|
234
|
+
### DFMResult Object
|
|
235
|
+
|
|
236
|
+
Contains all estimation outputs:
|
|
237
|
+
- **Factors**: `Z` (T × m), `C` (N × m)
|
|
238
|
+
- **Parameters**: `A` (m × m), `Q` (m × m), `R` (N × N)
|
|
239
|
+
- **Smoothed Data**: `X_sm` (T × N), `x_sm` (T × N)
|
|
240
|
+
- **Convergence**: `converged`, `num_iter`, `loglik`
|
|
241
|
+
- **Model Fit**: `rmse`, `rmse_per_series`
|
|
242
|
+
|
|
243
|
+
## Architecture
|
|
244
|
+
|
|
245
|
+
**Core Modules**:
|
|
246
|
+
- `config.py`: Configuration management (DFMConfig, SeriesConfig, BlockConfig, Params)
|
|
247
|
+
- `dfm.py`: Core estimation (DFM class with fit() method)
|
|
248
|
+
- `api.py`: High-level convenience API
|
|
249
|
+
- `kalman.py`: Kalman filter and smoother
|
|
250
|
+
- `news.py`: News decomposition
|
|
251
|
+
|
|
252
|
+
**Core Submodules**:
|
|
253
|
+
- `core/em.py`: EM algorithm core
|
|
254
|
+
- `core/numeric.py`: Numerical utilities
|
|
255
|
+
- `core/diagnostics.py`: Diagnostic functions
|
|
256
|
+
- `core/results.py`: Result metrics
|
|
257
|
+
- `core/grouping.py`: Frequency grouping utilities
|
|
258
|
+
|
|
259
|
+
## Testing
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
pytest src/test/ -v
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Tests are organized into 5 files:
|
|
266
|
+
- `test_dfm.py` - Core DFM estimation
|
|
267
|
+
- `test_kalman.py` - Kalman filter/smoother
|
|
268
|
+
- `test_news.py` - News decomposition
|
|
269
|
+
- `test_config.py` - Configuration and API
|
|
270
|
+
- `test_api.py` - Edge cases and tutorials
|
|
271
|
+
|
|
272
|
+
## Tutorials
|
|
273
|
+
|
|
274
|
+
1. **`tutorial/basic_tutorial.py`** - Spec CSV + Params approach
|
|
275
|
+
```bash
|
|
276
|
+
python tutorial/basic_tutorial.py --spec data/sample_spec.csv --data data/sample_data.csv
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
2. **`tutorial/hydra_tutorial.py`** - Hydra decorator approach
|
|
280
|
+
```bash
|
|
281
|
+
python tutorial/hydra_tutorial.py max_iter=10 threshold=1e-4
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Troubleshooting
|
|
285
|
+
|
|
286
|
+
**Convergence Issues**: Increase `max_iter`, relax `threshold`, check data quality
|
|
287
|
+
|
|
288
|
+
**Dimension Mismatch**: Ensure `series_id` matches data column names, verify block structure
|
|
289
|
+
|
|
290
|
+
**Numerical Instability**: Monitor warnings, adjust thresholds, investigate data quality
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
MIT License
|
|
295
|
+
|
|
296
|
+
## Citation
|
|
297
|
+
|
|
298
|
+
```bibtex
|
|
299
|
+
@software{dfm-python,
|
|
300
|
+
title = {dfm-python: Dynamic Factor Models for Nowcasting and Forecasting},
|
|
301
|
+
author = {DFM Python Contributors},
|
|
302
|
+
year = {2025},
|
|
303
|
+
url = {https://pypi.org/project/dfm-python/}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
**Package Status**: Stable (v0.2.1)
|
|
310
|
+
**PyPI**: https://pypi.org/project/dfm-python/
|
|
311
|
+
**Python**: 3.12+
|
|
312
|
+
**Latest Changes**: See [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
dfm_python/__init__.py,sha256=ym-3x_ucZaosWzko_4RtuhaT1TmFaFDSpJFWCk644YA,6870
|
|
2
|
+
dfm_python/api.py,sha256=u7Q9m1szVbnX2i1IDd98x4WI45h1AiEiVwBcIr2dbUY,16162
|
|
3
|
+
dfm_python/config.py,sha256=O3B6kPiXUTgPu2-eTzQE20M7-wzBIhxNzgAavIcuhYc,58416
|
|
4
|
+
dfm_python/data_loader.py,sha256=mQ8reju1A6psRF5F5r8B-2gBrHF0wf5en6vYKZ29ouI,30111
|
|
5
|
+
dfm_python/dfm.py,sha256=msb7VJjpkC3KKl3EuopG2YkVnf9wasT5o-ZMCOCFbyk,33963
|
|
6
|
+
dfm_python/kalman.py,sha256=PmXpi0HrhWJliZmx4Mwqg08dzZCPzo7gguLR5EhMCMU,17819
|
|
7
|
+
dfm_python/news.py,sha256=K2nZd2QA9oV2dN_2nT1iWd4-T6riNICTaUYaWCvTg1M,32599
|
|
8
|
+
dfm_python/core/__init__.py,sha256=RI8Q5-VB83wILo2C1_je3JMtkxANXnTy1D52YERXAHI,1684
|
|
9
|
+
dfm_python/core/diagnostics.py,sha256=aNEgIrbtpms-T3xHUE9TB41KxjDh7QVkeI-MjoHyG5A,14586
|
|
10
|
+
dfm_python/core/em.py,sha256=-KF3IQZwAekdV2ytrHNrN1W_L4WxX9V9H4-WFoBFSWw,49963
|
|
11
|
+
dfm_python/core/grouping.py,sha256=X-QHfb7-ZbQBO3GlrK6DszUWOc5xJ1-v3HlUGaqyO6w,1871
|
|
12
|
+
dfm_python/core/helpers.py,sha256=VGYnBYV-nECt_66q2UuNjfiehfvB1yPLg3Ru1Rdf7So,1505
|
|
13
|
+
dfm_python/core/numeric.py,sha256=wEtpKgmPu2fFDXAjF3AbZZfAQ5l2tJ88o5CnPfRGg8I,13318
|
|
14
|
+
dfm_python/core/results.py,sha256=qBTojSHgTADBVS7IcU8Ysz4CZKQjh95hLRGELV3KmTw,2378
|
|
15
|
+
dfm_python/utils/__init__.py,sha256=0OEbVuIp-cv49V7xlDn_38fHEVKyd_faNOY5gUViqa0,578
|
|
16
|
+
dfm_python/utils/aggregation.py,sha256=2Xg8xCiTkfUWTsBtYW84k1GFlBE3TBgFrjhqPn1lpUY,10170
|
|
17
|
+
dfm_python/utils/data_utils.py,sha256=w9RUKxk0FpcNaigBSPFNCzamIAmylUx8-KVzq3M8teY,8261
|
|
18
|
+
dfm_python-0.2.2.dist-info/METADATA,sha256=q4fE6mA7fPlEAM79rn-5z52fRUQIY3Y8owpG9vCEpk0,9678
|
|
19
|
+
dfm_python-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
20
|
+
dfm_python-0.2.2.dist-info/licenses/LICENSE,sha256=6e87br6LCDHjy2hdIR1-sdBQy351qdmSEbOg6jQ7ZXY,1063
|
|
21
|
+
dfm_python-0.2.2.dist-info/RECORD,,
|