fan_chart#
- cultivars.forecast.fan.fan_chart(paths, *, quantiles=(0.05, 0.16, 0.5, 0.84, 0.95))[source]#
Quantile paths of a predictive sample, per horizon and series.
For each horizon \(h\) and series \(j\), the empirical quantiles of the \(S\) draws at the stated levels,
\[q_{\tau}(h, j) = \hat F^{-1}_{h, j}(\tau), \qquad \tau \in \texttt{quantiles},\]stacked level by level. The quantiles are pointwise – each cell is computed on its own draws – so the bands describe the marginal predictive distribution at each horizon, not a joint band that a stated fraction of whole paths stays inside. The default levels give the 90% and 68% bands around the median, the convention of the Bank of England’s inflation fan.
- Parameters:
- Return type:
- Returns:
An array of shape
(len(quantiles), steps, k).- Raises:
DimensionError – If the paths are not three-dimensional.
SpecificationError – If the quantile levels are malformed.
Note
A data product, not a figure: the package draws nothing, and the levels are the caller’s to state, so a plotting routine reads row \(i\) of the result as the \(\tau_i\) band edge. NumPy’s default linear interpolation between order statistics is used, so with few draws the outer levels are interpolated from the sample’s extremes and should be read as approximate.
See also
quantiles()– the same computation on a conditional forecast’s paths.DensityScore– scores the paths the fan summarizes.
References
Britton, E., Fisher, P., & Whitley, J. (1998). The Inflation Report projections: Understanding the fan chart. Bank of England Quarterly Bulletin, 38(1), 30-37.
Example
Standard-normal draws recover the normal quantiles at every horizon; a single level returns one band:
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> fan = fan_chart(rng.standard_normal((4000, 6, 2))) >>> fan.shape (5, 6, 2) >>> fan[:, 0, 0].round(1) array([-1.6, -1. , 0. , 1. , 1.7]) >>> bool(np.all(np.diff(fan, axis=0) >= 0.0)) True >>> fan_chart(rng.standard_normal((100, 3, 1)), quantiles=(0.5,)).shape (1, 3, 1) >>> fan_chart(rng.standard_normal((100, 3, 1)), quantiles=(0.5, 0.2)) Traceback (most recent call last): ... cultivars.exceptions.SpecificationError: quantiles must be strictly increasing levels ...