Skip to content
1

Public Documentation

Documentation for ForecastEnsembles's public interface.

Contents

Index

Public API

ForecastEnsembles.BLP Type
julia
BLP(; weights = nothing)

Beta-transformed linear pool (Gneiting & Ranjan 2013): a recalibrated mixture that corrects the linear opinion pool's underdispersion by passing the mixture CDF through a fitted Beta CDF.

fit(BLP(), training, observations) fits the Beta to the linear pool's PIT values on the training set (maximum likelihood); combine(ft, fitted) applies it by evaluating the linear pool's quantile function at Beta-remapped levels. weights are the underlying per-model pool weights (equal by default, or any per-model EnsembleWeights / fitted method); the Beta parameters are learned on top. Quantile forecasts only.

Because the fit is a Beta on PIT values rather than a full weight regression, BLP is a recalibration of the pool: weights returns nothing (the level remap is not expressible as model weights), so apply it with combine(ft, fitted).

Fields

  • weights: per-model pool weights, or nothing for equal weights.
source
ForecastEnsembles.CRPSStacking Type
julia
CRPSStacking(; dirichlet_alpha = 1.001,
               lambda = nothing, time_col = nothing,
               task_weights = nothing)

CRPS-stacked linear opinion pool. Mirrors lopensemble::crps_weights, including its time weighting.

By default every training task contributes equally to the objective. Two ways to change that:

  • task_weights: a DataFrame with the training table's task-id columns plus a :weight column — one non-negative weight per task. The general mechanism; covers recency, per-region weighting (lopensemble's gamma), down-weighting anomalous reporting weeks, and so on.

  • lambda with time_col: convenience for recency weighting. time_col names the task column that orders tasks in time; lambda is one of

    • a scalar φ ∈ (0, 1]: exponential decay, weight φ^(T − t) for the t-th of T ordered unique time values (the common forecasting- literature choice; φ = 1 recovers equal weights),

    • :lopensemble: the quadratic ramp 2 − (1 − t/T)² that lopensemble::crps_weights uses by default (oldest ≈ 1, newest 2),

    • a Vector{Float64} with one weight per ordered unique time value (lopensemble's vector form),

    • a function of the normalised time rank t/T ∈ (0, 1] returning a weight.

lambda and task_weights are mutually exclusive. The Dirichlet prior strength scales with the effective sample size (Σλ)²/Σλ² rather than the raw task count, so heavy down-weighting of history does not quietly strengthen the prior relative to the data.

source
ForecastEnsembles.EnsembleMethod Type
julia
EnsembleMethod

Top of the method-type hierarchy. Subtypes split into

  • UnfittedMethod — can be passed to combine directly.

  • TrainedMethod — must be passed through fit first to obtain a fitted counterpart, which is itself an UnfittedMethod and can then be passed to combine.

source
ForecastEnsembles.EnsembleWeights Type
julia
EnsembleWeights(data; shape = :auto)

A typed container for per-model or per-quantile ensemble weights. The underlying data::DataFrame always has columns :model_id and :weight, and optionally :output_type_id. Two shapes are supported:

  • :per_model — columns :model_id, :weight. A single weight per model applied at every quantile/sample/etc.

  • :per_quantile — columns :model_id, :output_type_id, :weight. Weights vary across quantile levels.

Construct from a DataFrame (shape inferred from columns by default) or by calling weights(m) on a fitted method. MixtureEnsemble and QuantileEnsemble accept any of: a raw DataFrame, an EnsembleWeights, or any fitted method for which weights(m) returns one. The conversion happens at construction of the method, not at combine time, so invalid inputs fail fast.

source
ForecastEnsembles.FittedBLP Type
julia
FittedBLP(alpha, beta, weights)

Output of fit(::BLP, …). Stores the fitted Beta shape parameters alpha and beta and the underlying pool weights. alpha = beta = 1 means the linear pool was already calibrated (no transform). Apply with combine(ft, fitted); weights returns nothing.

source
ForecastEnsembles.FittedCRPSStacking Type
julia
FittedCRPSStacking(weights, models)

Output of fit(::CRPSStacking, …). Stores the simplex-constrained ensemble weights as a DataFrame with columns model_id and weight, the list of models these weights refer to, and crps, the fitted objective value (the mean CRPS achieved at the optimum). Plug into combine(ft, fitted) (sample inputs) — internally a LinearPool with these weights.

source
ForecastEnsembles.FittedHedge Type
julia
FittedHedge(weights, models, trajectory)

Output of fit(::Hedge, …). Stores the final simplex weights (a DataFrame with columns model_id and weight), the component models in weight order, and the trajectory — a long DataFrame (time_col, model_id, weight) of the weights after each update, for diagnosing weight stability over time. Plug into combine(ft, fitted) — internally a LinearPool with the final weights.

source
ForecastEnsembles.FittedInverseScore Type
julia
FittedInverseScore(weights, models, scores)

Output of fit(::InverseScore, …). Stores the simplex weights (a DataFrame with columns model_id and weight), the component models in weight order, and the per-member mean scores they were derived from. Plug into combine(ft, fitted) — internally a LinearPool with these weights.

source
ForecastEnsembles.FittedPartialPooling Type
julia
FittedPartialPooling(weights, global_weights, strata, models, score_value)

Output of fit(::PartialPooling, …). Stores the per-stratum weights (a DataFrame with the strata columns plus model_id and weight), the pooled global_weights (model_id, weight) used for strata not seen in training, the strata columns, the component models, and the mean score_value at the optimum. Plug into combine(ft, fitted) — it applies each stratum's weights, falling back to global_weights for an unseen stratum. weights(fitted) returns the pooled global vector as an EnsembleWeights.

source
ForecastEnsembles.FittedQRA Type
julia
FittedQRA(coefs, intercepts, models, levels, group_cols, per_quantile_weights, enforce_normalisation, has_intercept)

Output of fit(::QRA, …). coefs is a Dict{NamedTuple => Vector{Float64}} mapping a (group..., quantile_level) key to a vector of model coefficients in the order models. When per_quantile_weights is false, all keys sharing the same group share the same coefficients (and have the same key under a sentinel :any quantile_level).

Fields

  • coefs: Dict mapping each (group, quantile_level) key to its vector of model coefficients (ordered as models).

  • intercepts: Dict mapping each (group, quantile_level) key to its intercept; empty (all zero) when the fit has no intercept.

  • models: component model ids, giving the order of the coefficient vectors.

  • levels: the quantile levels the fit was trained on.

  • group_cols: the grouping task columns used when fitting; may be empty.

  • per_quantile_weights: Bool, whether coefficients vary across quantile levels.

  • enforce_normalisation: Bool, whether the simplex constraint (non-negative coefficients summing to one) was imposed.

  • has_intercept: Bool, whether an intercept was estimated.

source
ForecastEnsembles.FittedStacking Type
julia
FittedStacking(weights, models, score_value)

Output of fit(::Stacking, …). Stores the simplex ensemble weights (a DataFrame with columns model_id and weight), the component models in weight order, and the mean score_value achieved at the optimum. Plug into combine(ft, fitted) — internally a LinearPool with these weights.

source
ForecastEnsembles.ForecastTable Type
julia
ForecastTable

A long-format probabilistic-forecast table aligned with the hubverse model_out_tbl schema.

Required columns

  • the model identifier column (default :model_id)

  • :output_type — symbol, one of ForecastEnsembles.KNOWN_OUTPUT_TYPES

  • :output_type_id — quantile level, sample index, threshold, …

  • :value — the forecast value

  • one or more task-id columns (e.g. :location, :horizon, :target_date)

Construction

julia
ForecastTable(df; task_id_cols, model_id_col = :model_id)

task_id_cols may be omitted, in which case it is inferred as every column that is not one of the required columns.

Fields

  • data: the underlying long-format DataFrame holding the forecasts.

  • task_id_cols: the task-id columns identifying a forecast target.

  • model_id_col: the column naming the model that produced each forecast.

source
ForecastEnsembles.Hedge Type
julia
Hedge(score; eta = 1.0, time_col)

Online ensemble weighting by the Hedge / exponentiated-gradient rule.

fit(Hedge(score; time_col), training, observations) walks the distinct time_col values in order and, at each step, multiplies every member's weight by exp(-eta · sₜ) — where sₜ is that member's mean score on the current step (negatively oriented, so a lower score keeps more weight) — then renormalises to the simplex. A member absent at a step keeps its weight (a "sleeping expert"). The final weights plug into combine; the full trajectory is kept for weight-stability diagnostics.

Unlike InverseScore (one pooled score per member) this adapts to when members did well, so it tracks regime change; unlike Stacking it needs no optimiser and updates incrementally. score is any callable score(samples, y; w); ScoringRules is the natural companion (Hedge(ScoringRules.crps; time_col)), not a dependency of this package.

Fields

  • score: the scoring-rule function (negatively oriented).

  • eta: learning rate. Larger values adapt faster and concentrate weight more aggressively on recent winners; as it tends to 0 the weights stay uniform. Scale it to the magnitude of your score. Must be positive.

  • time_col: the task-id column defining the update order.

source
ForecastEnsembles.InverseScore Type
julia
InverseScore(score; temperature = 1.0)

Performance weighting: score each member independently and weight the better ones more heavily — wᵢ ∝ exp(−temperature · sᵢ), where sᵢ is member i's mean score over the training set (negatively oriented, so a lower score earns more weight). No optimisation, so it is fast and robust with few observations; but — unlike Stacking — it scores each member in isolation and never sees how they combine, so it is blind to redundancy between them.

fit(InverseScore(score), training, observations) returns a FittedInverseScore that plugs into combine / weights. score is any callable score(samples, y; w); ScoringRules is the natural companion (InverseScore(ScoringRules.crps)), not a dependency of this package.

Fields

  • score: the scoring-rule function (negatively oriented).

  • temperature: sharpness of the softmax over member scores. As it tends to 0 the weights approach equal; large values approach winner-take-all. Must be positive.

source
ForecastEnsembles.LinearPool Type
julia
MixtureEnsemble(; weights = nothing, n_samples = 10_000)

Mixture (linear-opinion-pool) ensemble: the ensemble distribution is the (weighted) mixture of the component distributions, F = Σᵢ wᵢ Fᵢ. The algorithm path depends on the forecast output_type:

  • :sample — weighted resample from per-model samples.

  • :cdf — pointwise weighted average of CDFs.

  • :quantile — reconstruct each model's CDF from its quantiles, draw n_samples, pool, and re-extract quantiles at the original levels.

Mixture pooling is fundamentally a per-model operation; per-quantile weights aren't meaningful here (use QuantileEnsemble for that).

source
ForecastEnsembles.LogarithmicPool Type
julia
LogarithmicPool(; weights = nothing, ngrid = 2000)

Logarithmic (geometric) opinion pool of quantile forecasts: the ensemble is the normalised weighted product of the member densities, f_ens(x) ∝ Πᵢ fᵢ(x)^wᵢ.

The geometric-mean counterpart of LinearPool (which averages the densities): the log pool is a product of experts, so it concentrates where the members agree and is typically sharper than the linear pool. weights are per-model (equal by default, or any per-model EnsembleWeights / fitted method) and act as the density exponents.

Each member's density is reconstructed from its quantiles (PCHIP interior, Normal tails), the log-product is formed on a grid of ngrid points, renormalised to integrate to one, and inverted at the requested levels. Quantile forecasts only.

Fields

  • weights: per-model exponent weights, or nothing for equal weights.

  • ngrid: number of grid points for the density product (higher is more accurate but slower).

source
ForecastEnsembles.MixtureEnsemble Type
julia
MixtureEnsemble(; weights = nothing, n_samples = 10_000)

Mixture (linear-opinion-pool) ensemble: the ensemble distribution is the (weighted) mixture of the component distributions, F = Σᵢ wᵢ Fᵢ. The algorithm path depends on the forecast output_type:

  • :sample — weighted resample from per-model samples.

  • :cdf — pointwise weighted average of CDFs.

  • :quantile — reconstruct each model's CDF from its quantiles, draw n_samples, pool, and re-extract quantiles at the original levels.

Mixture pooling is fundamentally a per-model operation; per-quantile weights aren't meaningful here (use QuantileEnsemble for that).

source
ForecastEnsembles.PartialPooling Type
julia
PartialPooling(score; strata, lambda = 1.0, dirichlet_alpha = 1.0)

Hierarchical (partially pooled) stacking: learn a weight vector per stratum that shrinks toward a shared global vector, so a data-sparse stratum borrows strength from the rest.

fit(PartialPooling(score; strata), training, observations) jointly optimises, in softmax space, one logit vector per distinct combination of the strata columns plus a global logit vector, minimising the mean score of each stratum's linearly-pooled forecast plus a shrinkage penalty pulling every stratum toward the global vector. The FittedPartialPooling result plugs into combine, which applies each stratum's own weights (an unseen stratum falls back to the global vector).

score is any callable score(samples, y; w); ScoringRules is the natural companion, not a dependency of this package. Generalises Stacking: a single stratum, or lambda → ∞, recovers global stacking.

Fields

  • score: the scoring-rule function to minimise (negatively oriented).

  • strata: task-id columns whose value combinations define the strata (e.g. [:location], [:location, :age_group]).

  • lambda: shrinkage strength toward the global vector. 0 fits each stratum independently; large values pool them toward one shared vector. Must be ≥ 0.

  • dirichlet_alpha: strength of a symmetric-Dirichlet prior on each stratum's weights, pulling them toward the simplex centre; 1.0 applies no prior.

source
ForecastEnsembles.QRA Type
julia
QRA(; per_quantile_weights = false, intercept = true,
      enforce_normalisation = false, noncross = false,
      group = Symbol[])

Quantile Regression Averaging. group lists task dimensions over which a separate regression is fitted. Mirrors qrensemble::qra.

source
ForecastEnsembles.QuantileEnsemble Type
julia
QuantileEnsemble(agg = :mean; weights = nothing)

Per-quantile weighted aggregation of quantile forecasts. At each task and quantile level τ, take a weighted mean (agg = :mean, also called Vincentization) or weighted median (agg = :median) of the per-model quantile values. weights may be:

  • nothing — equal weights (the "simple ensemble" of the hubverse).

  • a per-model EnsembleWeights — same weights at every τ.

  • a per-quantile EnsembleWeights — different weights per τ (e.g. from a per-τ QRA fit, or supplied externally).

  • any fitted method whose weights(m) returns one of the above (FittedCRPSStacking, FittedQRA in the right configuration, etc.).

source
ForecastEnsembles.Stacking Type
julia
Stacking(score; dirichlet_alpha = 1.0)

Score-optimal stacking against a user-supplied proper scoring rule.

fit(Stacking(score), training, observations) learns simplex ensemble weights that minimise the mean score of the linearly-pooled forecast, where score is any negatively-oriented rule from ScoringRules — e.g. ScoringRules.crps. The FittedStacking result plugs into combine, or into LinearPool/QuantileEnsemble via weights.

score is any callable score(samples, y; w); ScoringRules is the natural companion for it (using ScoringRules then Stacking(ScoringRules.crps)), but it is not a dependency of this package. CRPSStacking and QRA remain the closed-form specialisations for CRPS and WIS respectively.

Fields

  • score: the scoring-rule function to minimise (negatively oriented).

  • dirichlet_alpha: strength of a symmetric-Dirichlet prior on the weights, pulling them toward the simplex centre; 1.0 applies no prior.

source
ForecastEnsembles.TrainedMethod Type
julia
TrainedMethod

An ensemble method whose weights or coefficients are learned from past performance before use, for example QRA or CRPSStacking. Passing one through fit returns a fitted object (itself an UnfittedMethod) that can then be passed to combine.

source
ForecastEnsembles.TrimmedMean Type
julia
TrimmedMean(; fraction = 0.1, mode = :trim)

Robust ensemble mean. At each task and output_type_id (e.g. a quantile level τ), order the per-model values and either trim — drop the lowest and highest fraction of them, then average the rest — or winsorise — clamp those extremes to the surviving boundary values, then average all of them.

k = round(fraction · n) models are trimmed/clamped from each end, capped so at least one value always survives (so fraction → 0.5 degenerates to the median, fraction = 0 to the plain mean). This is the robust cousin of QuantileEnsemble(:mean): cheaper than a full median ensemble to reason about, and tunable in how much of the tail it discards. It aggregates values that are comparable across models at a shared output_type_id, so it supports :quantile and :cdf forecasts, not :sample (sample indices are not aligned across models — use MixtureEnsemble there).

Fields

  • fraction: proportion trimmed/clamped from each end, in [0, 0.5).

  • mode: :trim (drop the extremes) or :winsorise (clamp them).

Example

julia
using ForecastEnsembles, DataFrames
df = DataFrame(
    model_id = string.("m", 1:5),
    output_type = "quantile",
    output_type_id = 0.5,
    location = "A",
    value = [1.0, 2.0, 3.0, 4.0, 100.0]
)
ft = ForecastTable(df; task_id_cols = [:location])
combine(ft, TrimmedMean(; fraction = 0.2))
source
ForecastEnsembles.UnfittedMethod Type
julia
UnfittedMethod

An ensemble method applied directly to forecasts with no training, for example QuantileEnsemble(:mean) or MixtureEnsemble(). It carries any fixed configuration (aggregation rule, supplied weights) and can be passed straight to combine without a prior call to fit.

source
ForecastEnsembles.Windowed Type
julia
Windowed(method, window; time_col)

Wrap a TrainedMethod so it trains on only the most recent window values of time_col.

fit(Windowed(method, window; time_col), training, observations) keeps the last window distinct time_col values of training (and the matching observations), fits method on that subset, and returns method's own fitted result — so it drops straight into combine.

Useful for a rolling-window scheme in backtest: compare an expanding-window CRPSStacking() against a rolling Windowed(CRPSStacking(), 8; time_col = :date).

Fields

  • method: the inner TrainedMethod to fit on the window.

  • window: number of most-recent time_col values to train on (must be ≥ 1).

  • time_col: the task-id column defining time order.

source
ForecastEnsembles.backtest Function
julia
backtest(ft, observations, schemes; time_col, score_fn, min_train = 1,
         rng = default_rng()) -> DataFrame

Expanding-window backtest of ensemble schemes. The unique values of time_col are ordered; for each test time after the first min_train, every scheme is trained on the earlier times and scored on the test time out-of-sample. Returns one row per (scheme, test time) with columns scheme, the time_col, and :score (mean over that time's tasks).

schemes maps names to EnsembleMethods (a Dict or a vector of name => method pairs):

  • a TrainedMethodCRPSStacking(), QRA(...) — is fitted on the training window each fold, then applied to the test time;

  • an UnfittedMethodQuantileEnsemble(:mean), MixtureEnsemble() — is applied directly.

Each scheme must match the table's output_type: CRPSStacking and sample combiners need :sample data, QRA and quantile combiners need :quantile.

Scoring is the caller's choice: pass score_fn(forecast::ForecastTable, observations) -> Real (the mean score of one fold). ScoringRules.jl is a natural source — e.g. a CRPS-based scorer for sample forecasts — but any function of that shape works.

Aggregate across folds yourself, e.g.

julia
using DataFrames
res = backtest(ft, obs, schemes; time_col = :target_date)
combine(groupby(res, :scheme), :score => mean => :mean_score)

Arguments

  • ft: a ForecastTable.

  • observations: a DataFrame with the table's task-id columns and an :observed column.

  • schemes: a Dict or vector of name => EnsembleMethod pairs to compare.

Keyword Arguments

  • time_col: the column giving the time index to expand the window over.

  • min_train: number of initial times used only for training (default 1).

  • rng: RNG used by sample-based schemes (default default_rng()).

  • score_fn: a scorer (forecast, observations) -> Real, returning the mean score over the fold's tasks. Required — there is no default.

Examples

julia
using ForecastEnsembles, DataFrames, Random, Statistics
rng = MersenneTwister(1)
T = 12; K = 40
obs = DataFrame(t = 1:T, observed = randn(rng, T))
rows = DataFrame[]
for (mid, s) in (("m1", (y, r) -> y .+ randn(r, K)), ("m2", (y, r) -> 2 .* randn(r, K)))
    for t in 1:T
        push!(rows, DataFrame(model_id = mid, output_type = "sample",
            output_type_id = 1:K, t = t, value = s(obs.observed[t], rng)))
    end
end
ft = ForecastTable(reduce(vcat, rows); task_id_cols = [:t])
schemes = ["equal" => MixtureEnsemble(), "stack" => CRPSStacking()]

# Inject a scorer — here mean absolute error of the ensemble mean; with
# `using ScoringRules` you would instead pass a proper rule such as ScoringRules.crps.
function mae(ens, o)
    d = innerjoin(DataFrame(ens), o; on = :t)
    per = combine(groupby(d, :t),
        [:value, :observed] => ((v, y) -> abs(mean(v) - first(y))) => :e)
    return mean(per.e)
end

backtest(ft, obs, schemes; time_col = :t, min_train = 6, score_fn = mae)
source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::QuantileEnsemble) -> ForecastTable

Hub-style simple/weighted ensemble. Aggregates value across model_id within each (task, output_type, output_type_id) group, using m.agg (:mean or :median) and optional per-model weights.

Mirrors hubEnsembles::simple_ensemble. The output model_id is set to "hub-ensemble", matching the R package default.

source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::MixtureEnsemble; rng = default_rng()) -> ForecastTable

Linear opinion pool. The kernel is dispatched on the table's output_type:

  • :sample → weighted resampling of per-model samples to give a single pooled sample set per task (the only path that uses rng).

  • :cdf → weighted pointwise average of CDFs.

  • :quantile → reconstruct a continuous distribution per model via QuantileDistribution, then invert the mixture CDF Σᵢ wᵢ Fᵢ exactly by bisection at each input level. Deterministic — no Monte Carlo error, which matters for the extreme levels (τ = 0.01, 0.99) hubs request.

source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::LogarithmicPool; rng = default_rng()) -> ForecastTable

Apply the logarithmic (geometric) opinion pool at each task. See LogarithmicPool. The output model_id is "hub-ensemble".

source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::TrimmedMean; rng = default_rng()) -> ForecastTable

Apply a trimmed or winsorised cross-model mean at each (task, output_type_id). See TrimmedMean. The output model_id is "hub-ensemble".

source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::FittedQRA) -> ForecastTable

Apply fitted QRA weights to a new set of forecasts. The output has output_type = :quantile and one row per (task, quantile_level).

source
DataFrames.combine Method
julia
combine(ft::ForecastTable, m::FittedCRPSStacking; rng = default_rng()) -> ForecastTable

Apply CRPS-stacked weights to a (sample-typed) forecast table. Equivalent to combine(ft, LinearPool(weights = m.weights)).

Arguments

  • ft: a ForecastTable of sample forecasts.

  • m: a FittedCRPSStacking holding the fitted ensemble weights.

Keyword Arguments

  • rng: random number generator used for resampling; defaults to default_rng().

Example

julia
using ForecastEnsembles, DataFrames, Random
rng = MersenneTwister(1)
T = 20; K = 50
obs = DataFrame(t = 1:T, observed = randn(rng, T))
rows = DataFrame[]
for (mid, s) in (("m1", (y, r) -> y .+ randn(r, K)), ("m2", (y, r) -> 3 .* randn(r, K)))
    for t in 1:T
        push!(rows, DataFrame(model_id = mid, output_type = "sample",
            output_type_id = 1:K, t = t, value = s(obs.observed[t], rng)))
    end
end
ft = ForecastTable(reduce(vcat, rows); task_id_cols = [:t])
fitted = fit(CRPSStacking(), ft, obs)
combine(ft, fitted)
source
ForecastEnsembles.effective_num_models Function
julia
effective_num_models(m) -> Float64 or DataFrame

The effective number of models in a weight vector: the participation ratio of the normalised weights p. It is 1 when all weight sits on one model and equals the model count M when the weights are equal, so it reads as "how many models is this ensemble really using".

m may be a fitted method exposing weights (e.g. FittedCRPSStacking, FittedStacking, FittedHedge; FittedPartialPooling uses its pooled global vector), an EnsembleWeights, a weights DataFrame, or a raw weight vector. For per-quantile weights it returns a DataFrame (output_type_id, effective_num_models) — one value per quantile level; otherwise a scalar.

Example

julia
using ForecastEnsembles
effective_num_models([0.6, 0.3, 0.1])
source

Missing docstring.

Missing docstring for ForecastEnsembles.fit(::QRA, ::ForecastTable, ::DataFrames.AbstractDataFrame). Check Documenter's build log for details.

Missing docstring.

Missing docstring for ForecastEnsembles.fit(::CRPSStacking, ::ForecastTable, ::DataFrames.AbstractDataFrame). Check Documenter's build log for details.

ForecastEnsembles.model_ids Function
julia
model_ids(ft::ForecastTable) -> Vector

The distinct model identifiers present in ft, taken from its model-id column.

Arguments

Example

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])
model_ids(ft)
source
ForecastEnsembles.output_type Function
julia
output_type(ft::ForecastTable) -> Symbol

The single output_type present in ft. Throws if the table mixes output types, since most ensemble methods are defined on a single type at a time.

Arguments

Examples

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])
output_type(ft)
source
ForecastEnsembles.task_id_cols Function
julia
task_id_cols(ft::ForecastTable) -> Vector{Symbol}

The task-id columns of ft, i.e. the columns that together identify a forecast target (e.g. :location, :horizon, :target_date).

Arguments

Example

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])
task_id_cols(ft)
source
ForecastEnsembles.weight_stability Function
julia
weight_stability(m::FittedHedge) -> DataFrame

How much each model's Hedge weight moved over the training run: the total variation   of every model's weight along the fitted trajectory. A large value flags a model whose weight swung across the history (regime change or noise); a small one flags a stable contribution. Returns a DataFrame with columns model_id and total_variation.

Example

julia
using ForecastEnsembles, DataFrames
trajectory = DataFrame(
    model_id = repeat(["m1", "m2"], inner = 2),
    weight = [0.5, 0.7, 0.5, 0.3],
    t = [1, 2, 1, 2]
)
fitted = FittedHedge(
    DataFrame(model_id = ["m1", "m2"], weight = [0.7, 0.3]), ["m1", "m2"], trajectory)
weight_stability(fitted)
source
ForecastEnsembles.weights Function
julia
weights(m) -> Union{DataFrame, Nothing}

Per-model weights estimated by a fitted method, as a DataFrame with columns :model_id and :weight. Returns nothing when the fit does not correspond to a single weight vector on the simplex (e.g. unconstrained QRA, per-quantile QRA, QRA with a non-zero intercept).

When weights(m) !== nothing, m can be passed in place of an explicit weights frame to any method that accepts one — for example MixtureEnsemble(weights = m) or QuantileEnsemble(:mean; weights = m). This is the composition path between trained and untrained methods.

Arguments

Examples

julia
using ForecastEnsembles, DataFrames, Random
rng = MersenneTwister(1)
T = 20; K = 50
obs = DataFrame(t = 1:T, observed = randn(rng, T))
rows = DataFrame[]
for (mid, s) in (("m1", (y, r) -> y .+ randn(r, K)), ("m2", (y, r) -> 3 .* randn(r, K)))
    for t in 1:T
        push!(rows, DataFrame(model_id = mid, output_type = "sample",
            output_type_id = 1:K, t = t, value = s(obs.observed[t], rng)))
    end
end
ft = ForecastTable(reduce(vcat, rows); task_id_cols = [:t])
weights(fit(CRPSStacking(), ft, obs))
source