Skip to main content
Aggregating Exogenous Variables for Hierarchical Forecasting
When building forecasting models with exogenous (external) features, it is important that these features are also coherently aggregated across the hierarchy β€” just like the target variable. For example, if marketing_spend is available at the bottom level, the aggregated series at the state level should contain the sum of marketing spend across its child regions; while a rate-like variable such as cpi should be averaged. The aggregate function in HierarchicalForecast supports this through its exog_vars parameter: a dictionary mapping column names to their aggregation strategy (e.g., 'sum', 'mean', 'min', 'max'). This lets you aggregate exogenous variables alongside the target in a single call, and then use them as inputs to models that support exogenous regressors (e.g., AutoARIMA). In this notebook we demonstrate this workflow on the Australian Domestic Tourism dataset and compare forecasting performance with and without exogenous variables. You can run these experiments using CPU or GPU with Google Colab. Open In Colab

1. Load Data and Add Exogenous Variables

We start from the Tourism dataset and add two synthetic exogenous variables that illustrate different aggregation needs:
  • cpi β€” Consumer Price Index. This is a national-level economic indicator, identical across regions within each quarter. Because it is a rate (not a count), it should be averaged when aggregating.
  • marketing_spend β€” Regional marketing budget. This varies by state and grows over time. Because it represents a total amount, it should be summed when aggregating.
CountryRegionStatePurposedsy
0AustraliaAdelaideSouth AustraliaBusiness1998-01-01135.077690
1AustraliaAdelaideSouth AustraliaBusiness1998-04-01109.987316
2AustraliaAdelaideSouth AustraliaBusiness1998-07-01166.034687
3AustraliaAdelaideSouth AustraliaBusiness1998-10-01127.160464
4AustraliaAdelaideSouth AustraliaBusiness1999-01-01137.448533
CountryRegionStatePurposedsycpimarketing_spend
0AustraliaAdelaideSouth AustraliaBusiness1998-01-01135.077690100.649014190.7
1AustraliaAdelaideSouth AustraliaBusiness1998-04-01109.987316101.107535187.8
2AustraliaAdelaideSouth AustraliaBusiness1998-07-01166.034687101.801842183.5
3AustraliaAdelaideSouth AustraliaBusiness1998-10-01127.160464102.758750188.7
4AustraliaAdelaideSouth AustraliaBusiness1999-01-01137.448533103.188504190.3

2. Aggregate with Exogenous Variables

The exog_vars parameter of aggregate takes a dictionary where: - keys are the column names of the exogenous variables. - values are the aggregation function(s) to apply β€” any valid Pandas aggregation function name such as 'sum', 'mean', 'min', 'max', 'std'. The aggregated columns are named {column}_{function} (e.g., cpi_mean, marketing_spend_sum).
The result is a Y_agg DataFrame that contains both the aggregated target (y) and the aggregated exogenous variables (cpi_mean, marketing_spend_sum) for every level of the hierarchy.
unique_iddsycpi_meanmarketing_spend_sum
0Australia1998-01-0123182.197269100.64901436528.4
1Australia1998-04-0120323.380067101.10753536438.2
2Australia1998-07-0119826.640511101.80184236613.1
3Australia1998-10-0120830.129891102.75875036648.8
4Australia1999-01-0122087.353380103.18850437338.3
unique_iddsycpi_meanmarketing_spend_sum
560Australia/Victoria1998-01-016010.424491100.64901413711.9
561Australia/Victoria1998-04-014795.246755101.10753513640.1
562Australia/Victoria1998-07-014316.845170101.80184213742.9
563Australia/Victoria1998-10-014674.829118102.75875013768.8
564Australia/Victoria1999-01-015304.334195103.18850414047.9
unique_iddsycpi_meanmarketing_spend_sum
29920Australia/Victoria/Melbourne/Holiday1998-01-01427.827800100.649014160.2
29921Australia/Victoria/Melbourne/Holiday1998-04-01424.191925101.107535171.2
29922Australia/Victoria/Melbourne/Holiday1998-07-01449.551508101.801842168.8
29923Australia/Victoria/Melbourne/Holiday1998-10-01450.699582102.758750172.7
29924Australia/Victoria/Melbourne/Holiday1999-01-01412.358542103.188504175.8
Notice that: - cpi_mean is the same at every level (since CPI is identical across bottom series within each quarter). - marketing_spend_sum grows as we move up the hierarchy, because it sums the spend of all child series.

Multiple aggregations per variable

You can also apply multiple aggregation functions to a single variable by passing a list of strings.
unique_iddsymarketing_spend_summarketing_spend_meanmarketing_spend_std
560Australia/Victoria1998-01-016010.42449113711.9163.2369054.878618
561Australia/Victoria1998-04-014795.24675513640.1162.3821435.116737
562Australia/Victoria1998-07-014316.84517013742.9163.6059524.361285
563Australia/Victoria1998-10-014674.82911813768.8163.9142865.038578
564Australia/Victoria1999-01-015304.33419514047.9167.2369055.759074

3. Train/Test Split

We use the final two years (8 quarters) as test set. We also aggregate a version without exogenous variables to compare later.

4. Base Forecasts

We use AutoARIMA from StatsForecast, which supports exogenous regressors. Any column in the training data besides unique_id, ds, and y is treated as an exogenous feature. Future values are passed via X_df. We produce base forecasts with and without the exogenous variables for comparison.
unique_iddsAutoARIMA
0Australia2016-01-0126166.873073
1Australia2016-04-0124907.791984
2Australia2016-07-0124537.521142
3Australia2016-10-0125631.143759
4Australia2017-01-0126987.070921
unique_iddsAutoARIMA
0Australia2016-01-0126212.553553
1Australia2016-04-0125033.667125
2Australia2016-07-0124507.027198
3Australia2016-10-0125598.928613
4Australia2017-01-0126982.576796

5. Reconcile Forecasts

Reconciliation works exactly the same way regardless of whether exogenous variables were used to produce the base forecasts. The reconciliation step adjusts the base forecasts to be coherent across the hierarchy.
unique_iddsAutoARIMAAutoARIMA/BottomUpAutoARIMA/MinTrace_method-mint_shrink
0Australia2016-01-0126166.87307324461.29207225436.706581
1Australia2016-04-0124907.79198422795.93181724076.317511
2Australia2016-07-0124537.52114222151.77243523272.424691
3Australia2016-10-0125631.14375922936.26885024404.217321
4Australia2017-01-0126987.07092124292.35393225663.420421
unique_iddsAutoARIMAAutoARIMA/BottomUpAutoARIMA/MinTrace_method-mint_shrink
0Australia2016-01-0126212.55355324495.91998825322.734082
1Australia2016-04-0125033.66712522660.03626223873.068038
2Australia2016-07-0124507.02719822307.88750623396.655072
3Australia2016-10-0125598.92861322853.29486324303.043112
4Australia2017-01-0126982.57679624264.06507125520.638165

6. Evaluation

We compare RMSE and MASE across hierarchy levels for the models with and without exogenous variables.

RMSE

levelmetricBase (no exog)Base (w/ exog)BottomUp (no exog)BottomUp (w/ exog)MinTrace (no exog)MinTrace (w/ exog)
0Totalrmse773.97731.033247.043218.182029.461946.96
2Purposermse471.46516.06871.70859.13571.76545.22
4Statermse257.90251.32434.51431.99308.33298.49
6Regionsrmse56.5355.5358.1957.7946.4346.08
8Bottomrmse20.3920.4420.3920.4418.1318.22
10Overallrmse38.7238.7853.0052.7140.2639.58

MASE

levelmetricBase (no exog)Base (w/ exog)BottomUp (no exog)BottomUp (w/ exog)MinTrace (no exog)MinTrace (w/ exog)
1Totalmase0.760.733.393.362.011.91
3Purposemase1.141.412.482.491.451.48
5Statemase1.461.261.971.931.421.31
7Regionsmase1.211.201.251.241.021.00
9Bottommase1.021.021.021.020.940.95
11Overallmase1.061.061.101.100.970.97

References