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.
@@ -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
+ ]
@@ -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