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
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
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
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__ )
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
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
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__ )
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
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
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__ )