forecastpanel 0.1.1__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.
- forecastpanel/__init__.py +55 -0
- forecastpanel/_colors.py +148 -0
- forecastpanel/_core.py +639 -0
- forecastpanel/_dm.py +172 -0
- forecastpanel/_engine.py +217 -0
- forecastpanel/_evaluation.py +301 -0
- forecastpanel/_forecaster.py +409 -0
- forecastpanel/_panel.py +318 -0
- forecastpanel/_pca.py +57 -0
- forecastpanel/_plots.py +240 -0
- forecastpanel/_simulate.py +210 -0
- forecastpanel/_tables.py +233 -0
- forecastpanel/_version.py +1 -0
- forecastpanel/datasets/SOURCES.md +16 -0
- forecastpanel/datasets/__init__.py +92 -0
- forecastpanel/datasets/cpi_subindices.csv.gz +0 -0
- forecastpanel/datasets/house_prices.csv.gz +0 -0
- forecastpanel/datasets/house_weights.csv.gz +0 -0
- forecastpanel/datasets/macro_predictors.csv.gz +0 -0
- forecastpanel-0.1.1.dist-info/METADATA +623 -0
- forecastpanel-0.1.1.dist-info/RECORD +23 -0
- forecastpanel-0.1.1.dist-info/WHEEL +4 -0
- forecastpanel-0.1.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""forecastpanel: forecasting with panel data.
|
|
2
|
+
|
|
3
|
+
Individual, pooled, fixed- and random-effects, empirical Bayes and optimally
|
|
4
|
+
combined panel forecasts of Pesaran, Pick and Timmermann (2026), Quantitative
|
|
5
|
+
Economics 17(2), 342-393, doi:10.3982/QE2589, with evaluation tables, panel
|
|
6
|
+
Diebold-Mariano tests, Monte Carlo designs and multi-step scenario forecasts.
|
|
7
|
+
|
|
8
|
+
Author: Dr Merwan Roudane <merwanroudane920@gmail.com>
|
|
9
|
+
GitHub: https://github.com/merwanroudane/forecastpanel
|
|
10
|
+
"""
|
|
11
|
+
from ._version import __version__
|
|
12
|
+
from ._colors import (bluered_colors, matlab_jet_colors, parula_colors, resolve_cmap,
|
|
13
|
+
resolve_colorscale, sinha_colors, turbo_colors)
|
|
14
|
+
from ._core import (empirical_bayes, fixed_effects, half_jackknife, hierarchical_bayes,
|
|
15
|
+
individual_ols, iterative_bayes, mean_group, oracle_weights, pooled_ols,
|
|
16
|
+
random_effects_ar1_blup, random_effects_blup, weight_individual_fe,
|
|
17
|
+
weight_individual_pooled, weight_mallows, weight_stein, weights_unit_specific)
|
|
18
|
+
from ._dm import DMResult, dm_test, panel_dm_test
|
|
19
|
+
from ._engine import (ALL_METHODS, DEFAULT_METHODS, METHODS, PAPER_METHODS, PanelFit,
|
|
20
|
+
panel_forecasts)
|
|
21
|
+
from ._evaluation import EvaluationResults, evaluate_forecasts
|
|
22
|
+
from ._forecaster import ForecastResults, PanelForecaster, forecast_panel
|
|
23
|
+
from ._panel import PanelData, wide_to_long
|
|
24
|
+
from ._pca import principal_components
|
|
25
|
+
from ._plots import JOURNAL_RC, save_figure
|
|
26
|
+
from ._simulate import (DGPParameters, delta_ar_numerical, draw_parameters, monte_carlo,
|
|
27
|
+
panel_pr2, simulate_panel, table1_designs)
|
|
28
|
+
from .datasets import (load_cpi_panel, load_cpi_subindices, load_house_prices,
|
|
29
|
+
load_house_weights, load_macro_predictors)
|
|
30
|
+
|
|
31
|
+
__author__ = "Dr Merwan Roudane"
|
|
32
|
+
__email__ = "merwanroudane920@gmail.com"
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
# high-level
|
|
36
|
+
"PanelForecaster", "ForecastResults", "forecast_panel", "PanelData", "wide_to_long",
|
|
37
|
+
"evaluate_forecasts", "EvaluationResults", "panel_forecasts", "PanelFit",
|
|
38
|
+
"METHODS", "PAPER_METHODS", "DEFAULT_METHODS", "ALL_METHODS",
|
|
39
|
+
# estimators and weights
|
|
40
|
+
"individual_ols", "pooled_ols", "fixed_effects", "random_effects_blup",
|
|
41
|
+
"random_effects_ar1_blup", "empirical_bayes", "iterative_bayes", "mean_group",
|
|
42
|
+
"hierarchical_bayes", "half_jackknife", "weight_individual_pooled", "weight_individual_fe",
|
|
43
|
+
"weights_unit_specific", "weight_mallows", "weight_stein", "oracle_weights",
|
|
44
|
+
# tests
|
|
45
|
+
"dm_test", "panel_dm_test", "DMResult",
|
|
46
|
+
# simulation
|
|
47
|
+
"monte_carlo", "draw_parameters", "simulate_panel", "table1_designs", "panel_pr2",
|
|
48
|
+
"delta_ar_numerical", "DGPParameters", "principal_components",
|
|
49
|
+
# data
|
|
50
|
+
"load_house_prices", "load_house_weights", "load_cpi_subindices", "load_macro_predictors",
|
|
51
|
+
"load_cpi_panel",
|
|
52
|
+
# graphics
|
|
53
|
+
"parula_colors", "matlab_jet_colors", "turbo_colors", "bluered_colors", "sinha_colors",
|
|
54
|
+
"resolve_colorscale", "resolve_cmap", "JOURNAL_RC", "save_figure",
|
|
55
|
+
]
|
forecastpanel/_colors.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Colour maps shared with the author's R packages.
|
|
2
|
+
|
|
3
|
+
``parula_colors`` reproduces MATLAB's R2014b Parula colormap from its 64 RGB
|
|
4
|
+
stops; ``"Parula"`` is the default colour scale of every heatmap in the package.
|
|
5
|
+
|
|
6
|
+
Author: Dr Merwan Roudane <merwanroudane920@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import List, Sequence
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
PARULA_STOPS = np.array([
|
|
15
|
+
[0.2422, 0.1504, 0.6603], [0.2504, 0.1650, 0.7076], [0.2578, 0.1818, 0.7511],
|
|
16
|
+
[0.2647, 0.1978, 0.7952], [0.2706, 0.2147, 0.8364], [0.2751, 0.2342, 0.8710],
|
|
17
|
+
[0.2783, 0.2559, 0.8991], [0.2803, 0.2782, 0.9221], [0.2813, 0.3006, 0.9414],
|
|
18
|
+
[0.2810, 0.3228, 0.9579], [0.2795, 0.3447, 0.9717], [0.2760, 0.3667, 0.9829],
|
|
19
|
+
[0.2699, 0.3892, 0.9906], [0.2602, 0.4123, 0.9952], [0.2440, 0.4358, 0.9988],
|
|
20
|
+
[0.2206, 0.4603, 0.9973], [0.1963, 0.4847, 0.9892], [0.1834, 0.5074, 0.9798],
|
|
21
|
+
[0.1786, 0.5289, 0.9682], [0.1764, 0.5499, 0.9520], [0.1687, 0.5703, 0.9359],
|
|
22
|
+
[0.1540, 0.5902, 0.9218], [0.1460, 0.6091, 0.9079], [0.1380, 0.6276, 0.8973],
|
|
23
|
+
[0.1248, 0.6459, 0.8883], [0.1113, 0.6635, 0.8763], [0.0952, 0.6798, 0.8598],
|
|
24
|
+
[0.0689, 0.6948, 0.8394], [0.0297, 0.7082, 0.8163], [0.0036, 0.7203, 0.7917],
|
|
25
|
+
[0.0067, 0.7312, 0.7660], [0.0433, 0.7411, 0.7394], [0.0964, 0.7500, 0.7120],
|
|
26
|
+
[0.1408, 0.7584, 0.6842], [0.1717, 0.7670, 0.6554], [0.1938, 0.7758, 0.6251],
|
|
27
|
+
[0.2161, 0.7843, 0.5923], [0.2470, 0.7918, 0.5567], [0.2906, 0.7973, 0.5188],
|
|
28
|
+
[0.3406, 0.8008, 0.4789], [0.3909, 0.8029, 0.4354], [0.4456, 0.8024, 0.3909],
|
|
29
|
+
[0.5044, 0.7993, 0.3480], [0.5616, 0.7942, 0.3045], [0.6174, 0.7876, 0.2612],
|
|
30
|
+
[0.6720, 0.7793, 0.2227], [0.7242, 0.7698, 0.1910], [0.7738, 0.7598, 0.1646],
|
|
31
|
+
[0.8203, 0.7498, 0.1535], [0.8634, 0.7406, 0.1596], [0.9035, 0.7330, 0.1774],
|
|
32
|
+
[0.9393, 0.7288, 0.2100], [0.9728, 0.7298, 0.2394], [0.9956, 0.7434, 0.2371],
|
|
33
|
+
[0.9970, 0.7659, 0.2199], [0.9952, 0.7893, 0.2028], [0.9892, 0.8129, 0.1885],
|
|
34
|
+
[0.9786, 0.8360, 0.1766], [0.9676, 0.8587, 0.1643], [0.9610, 0.8806, 0.1537],
|
|
35
|
+
[0.9597, 0.9023, 0.1423], [0.9628, 0.9234, 0.1330], [0.9691, 0.9438, 0.1241],
|
|
36
|
+
[0.9769, 0.9839, 0.0805],
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
_JET = ["#000090", "#0000FF", "#00FFFF", "#FFFF00", "#FF0000", "#800000"]
|
|
40
|
+
_TURBO = ["#30123B", "#4145AB", "#4675ED", "#39A2FC", "#1BCFD4", "#24EAA7",
|
|
41
|
+
"#61FC6C", "#A4FC3C", "#D1E834", "#F3C63A", "#FE9B2D", "#F36315",
|
|
42
|
+
"#D93806", "#A91201", "#7A0403"]
|
|
43
|
+
_BLUERED = ["#053061", "#2166AC", "#92C5DE", "#F7F7F7", "#F4A582", "#B2182B", "#67001F"]
|
|
44
|
+
_SINHA = ["#000000", "#4A0E00", "#B22222", "#FF8C00", "#FFFF66"]
|
|
45
|
+
|
|
46
|
+
# Line colours and styles for forecasting methods (colour is always paired with
|
|
47
|
+
# a line style so figures survive greyscale printing).
|
|
48
|
+
METHOD_COLORS = ["#0072BD", "#D95319", "#EDB120", "#7E2F8E", "#77AC30",
|
|
49
|
+
"#4DBEEE", "#A2142F", "#000000", "#8C564B", "#E377C2",
|
|
50
|
+
"#17BECF", "#7F7F7F", "#BCBD22", "#1F77B4"]
|
|
51
|
+
METHOD_LINESTYLES = ["-", "--", "-.", ":", (0, (5, 1)), (0, (3, 1, 1, 1)),
|
|
52
|
+
(0, (1, 1)), "-", "--", "-.", ":", (0, (5, 2)),
|
|
53
|
+
(0, (3, 2, 1, 2)), "-"]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _hex(rgb: np.ndarray) -> List[str]:
|
|
57
|
+
rgb = np.clip(np.round(np.asarray(rgb) * 255), 0, 255).astype(int)
|
|
58
|
+
return ["#{:02X}{:02X}{:02X}".format(*c) for c in rgb]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _ramp(hex_stops: Sequence[str], n: int) -> List[str]:
|
|
62
|
+
"""Linear interpolation between hex stops (as R's ``colorRampPalette``)."""
|
|
63
|
+
if n < 1:
|
|
64
|
+
raise ValueError("n must be a positive integer")
|
|
65
|
+
stops = np.array([[int(h[i:i + 2], 16) / 255 for i in (1, 3, 5)] for h in hex_stops])
|
|
66
|
+
if n == 1:
|
|
67
|
+
return _hex(stops[:1])
|
|
68
|
+
pos = np.linspace(0, 1, len(stops))
|
|
69
|
+
grid = np.linspace(0, 1, n)
|
|
70
|
+
out = np.column_stack([np.interp(grid, pos, stops[:, j]) for j in range(3)])
|
|
71
|
+
return _hex(out)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def parula_colors(n: int = 256) -> List[str]:
|
|
75
|
+
"""MATLAB R2014b Parula colormap as ``n`` hex colours.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
n : int, default 256
|
|
80
|
+
Number of colours.
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
list of str
|
|
85
|
+
|
|
86
|
+
Examples
|
|
87
|
+
--------
|
|
88
|
+
>>> from forecastpanel import parula_colors
|
|
89
|
+
>>> parula_colors(3)
|
|
90
|
+
['#3E26A8', '#12BEBA', '#F9FB15']
|
|
91
|
+
"""
|
|
92
|
+
hexes = _hex(PARULA_STOPS)
|
|
93
|
+
if n == len(hexes):
|
|
94
|
+
return hexes
|
|
95
|
+
return _ramp(hexes, n)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def matlab_jet_colors(n: int = 256) -> List[str]:
|
|
99
|
+
"""MATLAB Jet colormap as ``n`` hex colours."""
|
|
100
|
+
return _ramp(_JET, n)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def turbo_colors(n: int = 256) -> List[str]:
|
|
104
|
+
"""Google Turbo colormap as ``n`` hex colours."""
|
|
105
|
+
return _ramp(_TURBO, n)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def bluered_colors(n: int = 256) -> List[str]:
|
|
109
|
+
"""Diverging blue-white-red colormap as ``n`` hex colours."""
|
|
110
|
+
return _ramp(_BLUERED, n)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def sinha_colors(n: int = 256) -> List[str]:
|
|
114
|
+
"""Sinha black-red-yellow colormap as ``n`` hex colours."""
|
|
115
|
+
return _ramp(_SINHA, n)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
_NAMED = {"parula": parula_colors, "jet": matlab_jet_colors, "turbo": turbo_colors,
|
|
119
|
+
"bluered": bluered_colors, "blue_red": bluered_colors,
|
|
120
|
+
"sinha": sinha_colors, "red_yellow_black": sinha_colors}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def resolve_cmap(name: str = "Parula", n: int = 256):
|
|
124
|
+
"""Return a matplotlib colormap for a named scale (default ``"Parula"``)."""
|
|
125
|
+
from matplotlib.colors import LinearSegmentedColormap
|
|
126
|
+
import matplotlib
|
|
127
|
+
|
|
128
|
+
key = str(name).lower()
|
|
129
|
+
if key in _NAMED:
|
|
130
|
+
return LinearSegmentedColormap.from_list(key, _NAMED[key](n), N=n)
|
|
131
|
+
return matplotlib.colormaps[name]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def resolve_colorscale(name: str = "Parula", n_breaks: int = 32):
|
|
135
|
+
"""Return a plotly colorscale ``[[0.0, '#..'], ...]`` for a named scale.
|
|
136
|
+
|
|
137
|
+
Native plotly names (``"Viridis"``, ``"RdBu"``, ...) are passed through.
|
|
138
|
+
"""
|
|
139
|
+
if isinstance(name, (list, tuple)):
|
|
140
|
+
return list(name)
|
|
141
|
+
key = str(name).lower()
|
|
142
|
+
if key in _NAMED:
|
|
143
|
+
cols = _NAMED[key](256)
|
|
144
|
+
n_breaks = max(2, int(n_breaks))
|
|
145
|
+
idx = np.round(np.linspace(0, len(cols) - 1, n_breaks)).astype(int)
|
|
146
|
+
vals = np.linspace(0, 1, n_breaks)
|
|
147
|
+
return [[float(v), cols[i]] for v, i in zip(vals, idx)]
|
|
148
|
+
return name.capitalize() if key.isalpha() else name
|