processing.forecast_scoring.aggregate_period_scores

processing.forecast_scoring.aggregate_period_scores(
    period_scores,
    *,
    entry_col='entry',
    period_col='period',
    metrics=None,
    rank_by='mae',
    ascending=True,
)

Aggregate per-period scores into a ranked leaderboard table.

Takes the long frame produced by score_forecasts_by_period (or any frame with an entry column, a period column, and numeric metric columns), averages every metric over each entry’s own periods, and ranks entries by rank_by with the number of scored periods breaking ties (more periods rank higher).

Parameters

Name Type Description Default
period_scores pd.DataFrame Long frame with one row per (entry, period). required
entry_col str Name of the entry column. Defaults to "entry". 'entry'
period_col str Name of the period column. Defaults to "period". 'period'
metrics Sequence[str] | None Metric columns to average. Defaults to None, which selects every numeric column except entry_col, period_col, and "n". None
rank_by str Metric that determines the ranking. Defaults to "mae". 'mae'
ascending bool Whether lower rank_by is better. Defaults to True. True

Returns

Name Type Description
pd.DataFrame pd.DataFrame: Indexed by entry, columns
pd.DataFrame [*metrics, "n_periods", "rank"], sorted by rank. rank
pd.DataFrame is 1-based.

Raises

Name Type Description
ValueError When period_scores is empty, a named column is missing, or rank_by is not among metrics.

Examples

import pandas as pd
from spotforecast2_safe.processing.forecast_scoring import (
    aggregate_period_scores,
    score_forecasts_by_period,
)

idx = pd.date_range("2026-06-10", periods=72, freq="h", tz="UTC")
actual = pd.Series([40_000.0] * 72, index=idx)
daily = score_forecasts_by_period(
    {"good": actual + 50.0, "bad": actual + 900.0},
    actual,
    metrics=("mae", "bias"),
)
board = aggregate_period_scores(daily, rank_by="mae")
print(board.round(1).to_string())
assert list(board.index) == ["good", "bad"]
assert list(board["rank"]) == [1, 2]
         mae   bias  n_periods  rank
entry                               
good    50.0   50.0          3     1
bad    900.0  900.0          3     2