Hierarchical Methods Time series forecasting
—
Plotting utilities for visualizing hierarchical time series data, reconciliation results, and hierarchy structures. The visualization tools help explore hierarchical relationships, compare forecasts across methods, and understand the impact of reconciliation.
Main visualization class that provides methods for plotting hierarchical time series data and reconciliation results.
class HierarchicalPlot:
"""
Visualization utilities for hierarchical forecasts.
Provides plotting methods for exploring hierarchical time series data,
reconciliation results, and hierarchy structures.
"""
def __init__(
self,
S: Frame,
tags: dict[str, np.ndarray],
S_id_col: str = 'unique_id'
):
"""
Initialize HierarchicalPlot object.
Parameters:
- S: DataFrame representing the summing matrix
- tags: dict mapping hierarchy level names to series indices
- S_id_col: str, column name for series identifier in summing matrix
"""Visualize the structure of the summing matrix to understand hierarchical relationships.
def plot_summing_matrix(self) -> None:
"""
Visualize the summing matrix structure.
Creates a heatmap showing the aggregation relationships between
bottom-level series and all hierarchy levels. Useful for understanding
the hierarchical structure and identifying potential issues.
The plot shows:
- Rows: All series in the hierarchy (bottom and aggregated)
- Columns: Bottom-level series
- Values: Binary indicators (1 if bottom series contributes to aggregate, 0 otherwise)
"""Plot individual time series with forecasts and prediction intervals.
def plot_series(
self,
series: str,
Y_df: Frame,
models: list[str] = None,
level: list[int] = None,
engine: str = 'matplotlib',
xlabel: str = None,
ylabel: str = None,
title: str = None,
id_col: str = 'unique_id',
time_col: str = 'ds',
target_col: str = 'y',
**kwargs
) -> None:
"""
Plot individual time series with forecasts.
Parameters:
- series: str, name of the series to plot
- Y_df: DataFrame with historical data and forecasts
- models: list of model names to include in plot
- level: list of confidence levels for prediction intervals
- engine: str, plotting engine ('matplotlib' or 'plotly')
- xlabel: str, x-axis label
- ylabel: str, y-axis label
- title: str, plot title
- id_col: str, identifier column name
- time_col: str, time column name
- target_col: str, target variable column name
- **kwargs: additional plotting arguments
Creates a plot showing:
- Historical values (if available)
- Point forecasts for each model
- Prediction intervals (if level specified)
- Legend identifying different models and intervals
"""Plot all series in the hierarchy that are linked to a specific bottom-level series.
def plot_hierarchically_linked_series(
self,
bottom_series: str,
Y_df: Frame,
models: list[str] = None,
level: list[int] = None,
engine: str = 'matplotlib',
xlabel: str = None,
ylabel: str = None,
id_col: str = 'unique_id',
time_col: str = 'ds',
target_col: str = 'y',
**kwargs
) -> None:
"""
Plot all series hierarchically linked to a bottom series.
Parameters:
- bottom_series: str, name of the bottom-level series
- Y_df: DataFrame with hierarchical data and forecasts
- models: list of model names to plot
- level: list of confidence levels for intervals
- engine: str, plotting engine
- xlabel: str, x-axis label
- ylabel: str, y-axis label
- id_col: str, identifier column name
- time_col: str, time column name
- target_col: str, target variable column name
- **kwargs: additional plotting arguments
Creates subplots showing:
- The specified bottom series
- All aggregate series that include this bottom series
- Forecasts and intervals for each hierarchy level
"""Visualize prediction gaps across different hierarchy levels to assess reconciliation quality.
def plot_hierarchical_predictions_gap(
self,
Y_df: Frame,
models: list[str] = None,
xlabel: str = None,
ylabel: str = None,
id_col: str = 'unique_id',
time_col: str = 'ds',
**kwargs
) -> None:
"""
Plot prediction gaps across hierarchy levels.
Parameters:
- Y_df: DataFrame with forecasts at different hierarchy levels
- models: list of model names to analyze
- xlabel: str, x-axis label
- ylabel: str, y-axis label
- id_col: str, identifier column name
- time_col: str, time column name
- **kwargs: additional plotting arguments
Creates visualization showing:
- Differences between aggregated bottom-up forecasts and direct forecasts
- Gap magnitude across different hierarchy levels
- Comparison across reconciliation methods
- Time evolution of coherence gaps
"""Context manager for timing code execution, useful for performance analysis.
class CodeTimer:
"""
Context manager for timing code execution.
Useful for measuring performance of reconciliation methods
and data processing operations.
"""
def __init__(self, name: str = None):
"""
Initialize CodeTimer.
Parameters:
- name: str, optional name for the timer (for identification)
"""
def __enter__(self):
"""Start timing when entering context."""
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Stop timing and report duration when exiting context."""import pandas as pd
import numpy as np
from hierarchicalforecast.utils import HierarchicalPlot
# Assume we have hierarchical data and forecasts
hierarchical_data = pd.DataFrame({
'unique_id': ['A', 'B', 'Total'] * 10,
'ds': pd.date_range('2020-01-01', periods=10, freq='D').tolist() * 3,
'y': np.random.randn(30).cumsum() + 100,
'BottomUp': np.random.randn(30).cumsum() + 100,
'MinTrace': np.random.randn(30).cumsum() + 100
})
# Tags mapping hierarchy levels
tags = {
'Bottom': np.array([0, 1]), # Series A and B
'Total': np.array([2]) # Aggregated series
}
# Summing matrix
S_df = pd.DataFrame({
'unique_id': ['A', 'B', 'Total'],
'A': [1, 0, 1],
'B': [0, 1, 1]
})
# Create plotting object
plotter = HierarchicalPlot(S=S_df, tags=tags)# Plot the summing matrix to understand hierarchy structure
plotter.plot_summing_matrix()# Plot a specific series with multiple models
plotter.plot_series(
series='Total',
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
title='Total Series Forecasts',
xlabel='Date',
ylabel='Value'
)# Data with prediction intervals
data_with_intervals = hierarchical_data.copy()
data_with_intervals['BottomUp-lo-80'] = data_with_intervals['BottomUp'] - 10
data_with_intervals['BottomUp-hi-80'] = data_with_intervals['BottomUp'] + 10
data_with_intervals['MinTrace-lo-80'] = data_with_intervals['MinTrace'] - 8
data_with_intervals['MinTrace-hi-80'] = data_with_intervals['MinTrace'] + 8
# Plot with intervals
plotter.plot_series(
series='Total',
Y_df=data_with_intervals,
models=['BottomUp', 'MinTrace'],
level=[80], # 80% prediction intervals
title='Forecasts with Prediction Intervals'
)# Show all series linked to bottom series 'A'
plotter.plot_hierarchically_linked_series(
bottom_series='A',
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
xlabel='Date',
ylabel='Value'
)# Plot prediction gaps to assess reconciliation quality
plotter.plot_hierarchical_predictions_gap(
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
xlabel='Date',
ylabel='Gap Magnitude'
)# Use plotly for interactive plots (if available)
plotter.plot_series(
series='Total',
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
engine='plotly',
title='Interactive Forecast Plot'
)from hierarchicalforecast.utils import CodeTimer
# Time reconciliation operations
with CodeTimer("MinTrace Reconciliation"):
reconciled = min_trace.fit_predict(
S=summing_matrix,
y_hat=forecasts,
y_insample=historical_data
)
# Time multiple operations
operations = {
'BottomUp': lambda: bottom_up.fit_predict(S, forecasts, bottom_indices),
'TopDown': lambda: top_down.fit_predict(S, forecasts, tags, historical_data),
'MinTrace': lambda: min_trace.fit_predict(S, forecasts, historical_data)
}
timing_results = {}
for name, operation in operations.items():
with CodeTimer(name) as timer:
result = operation()
timing_results[name] = timer.elapsed_time# Custom styling and additional parameters
plotter.plot_series(
series='Total',
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
title='Custom Styled Forecast Plot',
xlabel='Time Period',
ylabel='Sales Units',
figsize=(12, 6), # Custom figure size
linewidth=2, # Line width
alpha=0.7, # Transparency
grid=True, # Show grid
legend_loc='upper left' # Legend position
)# Create plots for each hierarchy level
hierarchy_levels = ['A', 'B', 'Total']
for level in hierarchy_levels:
plotter.plot_series(
series=level,
Y_df=hierarchical_data,
models=['BottomUp', 'MinTrace'],
title=f'Forecasts for {level}',
ylabel='Value'
)Install with Tessl CLI
npx tessl i tessl/pypi-hierarchicalforecast