Getting started
ForecastEnsembles.jl combines several probabilistic forecasts of the same target into one. Everything works on a ForecastTable, a long-format frame aligned with the hubverse model_out_tbl schema, and every method is applied with one of two verbs: combine to aggregate, fit to estimate weights from past performance first.
Combine three forecasts
Wrap the component forecasts and take an equal-weight quantile mean, the combination a hub reaches for first:
using ForecastEnsembles, DataFrames
df = DataFrame(
location = "A", horizon = 1,
model_id = repeat(["m1", "m2", "m3"], inner = 2),
output_type = "quantile",
output_type_id = repeat([0.25, 0.75], 3),
value = [1.0, 3.0, 2.0, 4.0, 0.5, 2.5]
)
ft = ForecastTable(df; task_id_cols = [:location, :horizon])
DataFrame(combine(ft, QuantileEnsemble(:mean)))| Row | model_id | output_type | output_type_id | location | horizon | value |
|---|---|---|---|---|---|---|
| String | Symbol | Float64 | String | Int64 | Float64 | |
| 1 | hub-ensemble | quantile | 0.25 | A | 1 | 1.16667 |
| 2 | hub-ensemble | quantile | 0.75 | A | 1 | 3.16667 |
The task-id columns say what identifies a single forecast target: here one location at one horizon. Models are combined within each of those groups.
Next: choose how to weight
Equal weights are the default, not a requirement. Weights can be supplied directly:
w = EnsembleWeights(DataFrame(
model_id = ["m1", "m2", "m3"],
weight = [0.5, 0.3, 0.2]
))
DataFrame(combine(ft, MixtureEnsemble(; weights = w)))| Row | model_id | output_type | output_type_id | location | horizon | value |
|---|---|---|---|---|---|---|
| String | Symbol | Float64 | String | Int64 | Float64 | |
| 1 | hub-ensemble | quantile | 0.25 | A | 1 | 1.11186 |
| 2 | hub-ensemble | quantile | 0.75 | A | 1 | 3.27473 |
That changed two things at once, though: the weights and the combination operation. QuantileEnsemble averages quantile values at each level, while MixtureEnsemble averages the distributions themselves, and they differ even on equal weights:
DataFrame(combine(ft, MixtureEnsemble()))| Row | model_id | output_type | output_type_id | location | horizon | value |
|---|---|---|---|---|---|---|
| String | Symbol | Float64 | String | Int64 | Float64 | |
| 1 | hub-ensemble | quantile | 0.25 | A | 1 | 1.05943 |
| 2 | hub-ensemble | quantile | 0.75 | A | 1 | 3.26052 |
Choosing between them is the first of the two decisions the Methods page sets out.
Next: estimate weights from past forecasts
Where past forecasts and observations are available, weights can be estimated rather than chosen, by minimising a score on that history:
fitted = fit(CRPSStacking(), training_forecasts, observations)
combine(ft, MixtureEnsemble(; weights = fitted))QRA works on quantile forecasts; CRPSStacking and the score-driven estimators, which take a scoring function you supply, need sample forecasts. The worked example runs all of them on a real hubverse slice.
Where to go next
Methods — the two axes (how members are combined, how they are weighted) and every method on each.
Worked example — the whole interface on real hub data.
Public API — the full reference.
Problems or questions: open an issue on the GitHub repository.
The layout, navigation, and infrastructure of this site are generated by EpiAwarePackageTools.