← Back to learnwithForhad

Hierarchical Forecasting in R with fable

How to build coherent hierarchical forecasts using fable and reconciliation methods — from store-level to national-level, all adding up correctly.


The Coherence Problem

Imagine you forecast sales for 50 stores individually. You also forecast total national sales. Do the 50 store forecasts add up to the national forecast? Almost never. That's the coherence problem, and it's everywhere — retail, finance, supply chain.

Hierarchical forecasting solves this by forecasting at every level of the hierarchy and then reconciling the forecasts so they're consistent.

Setting Up the Hierarchy

R's fable ecosystem makes this elegant. You define your hierarchy using tsibble aggregation keys:

library(fable)
library(tsibble)
library(tidyverse)

sales_tsbl <- sales_data %>%
  as_tsibble(key = c(region, store), index = month)

# Aggregate to create the hierarchy
sales_hierarchy <- sales_tsbl %>%
  aggregate_key(region / store, sales = sum(sales))

This creates a tsibble with three levels: total (national), region, and store. The / operator defines the nesting.

Forecasting at Every Level

Fit models to every series in the hierarchy simultaneously:

fit <- sales_hierarchy %>%
  model(
    ets   = ETS(sales),
    arima = ARIMA(sales)
  )

fc <- fit %>%
  forecast(h = 12)

Reconciliation

The magic happens here. reconcile() adjusts the forecasts so they add up:

fc_reconciled <- fit %>%
  reconcile(
    ets_bu   = bottom_up(ets),
    ets_mint = min_trace(ets, method = "mint_shrink"),
    arima_bu = bottom_up(arima)
  ) %>%
  forecast(h = 12)

The main reconciliation approaches:

Real-World Results

In our retail case study, MinT reconciliation improved forecast accuracy by 8–15% at the store level compared to independent forecasts. The national-level forecasts barely changed — but the store-level ones got dramatically better because they borrowed strength from the aggregate.

Takeaway

If you're forecasting at multiple levels of granularity, you need reconciliation. The fable ecosystem makes it a few lines of code. Start with MinT shrinkage — it's the best default for most real-world hierarchies.