plots.evaluation

plots.evaluation

Campaign-level evaluation plots for forecasting entries over time.

Generalises the daily-metric timeline, hour-of-day error profile, and day-ahead forecast overlay of a manuscript’s results section into a reusable, stateless API. All functions return a matplotlib.figure.Figure; the caller is responsible for saving and closing it. None of them call plt.show() nor mutate matplotlib.rcParams — styling and figure lifecycle stay with the caller (set matplotlib.use("Agg") before importing pyplot in headless environments).

Functions

Name Description
plot_error_profile Mean-error-by-group profile for one or more entries (e.g. hour of day).
plot_forecast_overlay One or more forecasts overlaid against an optional actual series.
plot_metric_timeline Daily-metric timeline for one or more entries, with an optional range band.

plot_error_profile

plots.evaluation.plot_error_profile(
    profile,
    *,
    colors=None,
    linewidth=1.8,
    marker='o',
    marker_size=3.0,
    zero_line=True,
    zero_line_color='black',
    xlabel='',
    ylabel='mean error',
    xticks=None,
    legend_loc='lower center',
    ax=None,
    figsize=(6.3, 2.7),
)

Mean-error-by-group profile for one or more entries (e.g. hour of day).

profile has one row per grouping key (e.g. hour of day, 0-23) and one column per entry; each column is drawn as its own line.

Parameters

Name Type Description Default
profile pd.DataFrame DataFrame indexed by the grouping key, one column per entry. required
colors Mapping[str, str] | None Mapping of column name to line color. Columns missing from the mapping use matplotlib’s default color cycle. None
linewidth float Line width for every entry. 1.8
marker str Marker style for every entry. 'o'
marker_size float Marker size for every entry. 3.0
zero_line bool When True, draw a horizontal reference line at 0. True
zero_line_color str Color of the zero reference line. 'black'
xlabel str X-axis label. ''
ylabel str Y-axis label. 'mean error'
xticks Sequence[float] | None Explicit tick positions for the x axis. When None, the default matplotlib ticks are kept. None
legend_loc str loc argument forwarded to ax.legend. 'lower center'
ax Axes | None Existing axes to draw into. When given, no new figure is created and the function returns ax.figure. None
figsize tuple[float, float] Figure size used when ax is not given. (6.3, 2.7)

Returns

Name Type Description
Figure A matplotlib.figure.Figure.

Examples

import numpy as np
import pandas as pd
from spotforecast2.plots.evaluation import plot_error_profile

rng = np.random.default_rng(0)
profile = pd.DataFrame(
    {
        "forecaster": rng.normal(0, 100, 24),
        "baseline": rng.normal(-200, 150, 24),
    },
    index=range(24),
)
fig = plot_error_profile(profile, xticks=range(0, 24, 3))
print(type(fig).__name__)
Figure

plot_forecast_overlay

plots.evaluation.plot_forecast_overlay(
    forecasts,
    *,
    actual=None,
    actual_label='actual',
    actual_color='black',
    x='index',
    colors=None,
    linestyles=None,
    linewidth=1.8,
    xlabel='',
    ylabel='',
    xticks=None,
    legend_loc='lower center',
    ax=None,
    figsize=(6.3, 2.9),
)

One or more forecasts overlaid against an optional actual series.

actual, when given, is drawn first and slightly thicker than the forecast lines (linewidth + 0.2) so it reads as the reference trace. Each entry in forecasts is then drawn in insertion order.

Parameters

Name Type Description Default
forecasts Mapping[str, pd.Series] Mapping of entry name to forecast series. required
actual pd.Series | None Optional realised/ground-truth series, drawn first. None
actual_label str Legend label for actual. 'actual'
actual_color str Line color for actual. 'black'
x str "index" plots every series against its own index as-is; "hour" plots against index.hour (e.g. to overlay several day-ahead forecasts for the same target day on a 0-23 axis). 'index'
colors Mapping[str, str] | None Mapping of entry name to line color. Entries missing from the mapping use matplotlib’s default color cycle. None
linestyles Mapping[str, str] | None Mapping of entry name to a matplotlib linestyle (e.g. {"baseline": "--"}). Entries missing from the mapping are drawn solid. None
linewidth float Line width for the forecast lines. 1.8
xlabel str X-axis label. ''
ylabel str Y-axis label. ''
xticks Sequence[float] | None Explicit tick positions for the x axis. When None, the default matplotlib ticks are kept. None
legend_loc str loc argument forwarded to ax.legend. 'lower center'
ax Axes | None Existing axes to draw into. When given, no new figure is created and the function returns ax.figure. None
figsize tuple[float, float] Figure size used when ax is not given. (6.3, 2.9)

Returns

Name Type Description
Figure A matplotlib.figure.Figure.

Examples

import numpy as np
import pandas as pd
from spotforecast2.plots.evaluation import plot_forecast_overlay

idx = pd.date_range("2024-01-15", periods=24, freq="h", tz="UTC")
rng = np.random.default_rng(0)
actual = pd.Series(40_000 + rng.standard_normal(24) * 500, index=idx)
forecasts = {
    "forecaster": actual + rng.standard_normal(24) * 300,
    "baseline": actual + rng.standard_normal(24) * 800,
}
fig = plot_forecast_overlay(
    forecasts,
    actual=actual,
    x="hour",
    linestyles={"baseline": "--"},
    xticks=range(0, 24, 3),
)
print(type(fig).__name__)
Figure

plot_metric_timeline

plots.evaluation.plot_metric_timeline(
    series,
    *,
    band=None,
    band_label='range',
    band_color='0.9',
    colors=None,
    linewidth=1.8,
    ylabel='',
    legend_loc='upper right',
    ax=None,
    figsize=(6.3, 2.9),
)

Daily-metric timeline for one or more entries, with an optional range band.

Each series in series is plotted over its own (datetime) index after dropna(), so entries that join or leave the campaign at different dates are drawn only over their own scored period. When band is given, its row-wise min/max is drawn as a filled band underneath the lines (e.g. the range spanned by a group of reference entries).

Parameters

Name Type Description Default
series Mapping[str, pd.Series] Mapping of entry name to a metric series with a datetime index (e.g. daily MAE). required
band pd.DataFrame | None Optional DataFrame whose row-wise min and max are filled between (e.g. the daily metric of a group of entries). Its index must be datetime-like and comparable to the series indices. None
band_label str Legend label for the band. 'range'
band_color str Fill color for the band. '0.9'
colors Mapping[str, str] | None Mapping of entry name to line color. Entries missing from the mapping use matplotlib’s default color cycle. None
linewidth float Line width for every series. 1.8
ylabel str Y-axis label. ''
legend_loc str loc argument forwarded to ax.legend. 'upper right'
ax Axes | None Existing axes to draw into. When given, no new figure is created and the function returns ax.figure. None
figsize tuple[float, float] Figure size used when ax is not given. (6.3, 2.9)

Returns

Name Type Description
Figure A matplotlib.figure.Figure.

Examples

import numpy as np
import pandas as pd
from spotforecast2.plots.evaluation import plot_metric_timeline

idx = pd.date_range("2024-01-01", periods=14, freq="D")
rng = np.random.default_rng(0)
series = {
    "forecaster": pd.Series(500 + rng.standard_normal(14) * 20, index=idx),
    "baseline": pd.Series(700 + rng.standard_normal(14) * 20, index=idx),
}
band = pd.DataFrame(
    {f"peer_{i}": 550 + rng.standard_normal(14) * 40 for i in range(4)},
    index=idx,
)
fig = plot_metric_timeline(series, band=band, ylabel="daily MAE (MW)")
print(type(fig).__name__)
Figure