Skip to content
1

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:

julia
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)))
2×6 DataFrame
Rowmodel_idoutput_typeoutput_type_idlocationhorizonvalue
StringSymbolFloat64StringInt64Float64
1hub-ensemblequantile0.25A11.16667
2hub-ensemblequantile0.75A13.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:

julia
w = EnsembleWeights(DataFrame(
    model_id = ["m1", "m2", "m3"],
    weight = [0.5, 0.3, 0.2]
))

DataFrame(combine(ft, MixtureEnsemble(; weights = w)))
2×6 DataFrame
Rowmodel_idoutput_typeoutput_type_idlocationhorizonvalue
StringSymbolFloat64StringInt64Float64
1hub-ensemblequantile0.25A11.11186
2hub-ensemblequantile0.75A13.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:

julia
DataFrame(combine(ft, MixtureEnsemble()))
2×6 DataFrame
Rowmodel_idoutput_typeoutput_type_idlocationhorizonvalue
StringSymbolFloat64StringInt64Float64
1hub-ensemblequantile0.25A11.05943
2hub-ensemblequantile0.75A13.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:

julia
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.