Reconciliation of structured time series forecasts with graphs
8th Sept 2023 @ IIF Reconciliation Workshop
Mitchell O’Hara-Wild, Monash University
Supervised by Rob Hyndman and George Athanasopolous

Each aggregate has a single constraint
The basic constraint shown before is ‘hierarchical’
Each aggregate has a single constraint
Hierarchical series often have multiple layers
In graph terms, this is known as a polytree.
Considering origin and workplace
Attendance can be disaggregated by both origin and workplace…
Considering origin and workplace
and then further disaggregated by the other.
A grouped structure has the same top and bottom series.
Considering origin and workplace
The grouped structure can be plotted in a single graph.
In graph terms, this is a directed acyclical graph (DAG).
A time series can be disaggregated by temporal granularity
Temporal reconciliation is described in Athanasopoulos et al. (2017).
What type of coherence structure is this?
This is a polytree, so this structure is hierarchical.
What type of coherence structure is this?
This structure has the same top and bottom series, so
temporal coherence is a grouped constraint.
Temporal coherence constraints are grouped can also be represented with directed acyclical graphs (DAGs).
Since both grouped and temporal coherence are DAGs, the interaction between them is a single DAG.
A directed acyclical graph does not require a common top and bottom series.
What happens if we relax this definition of grouped coherence, and use the more general DAG structure.
Is it reasonable to leverage the full generality of DAGs?
Yes! Let’s see why.
What if the coherency structure had different bottom series?
This often occurs in these circumstances:
Example
Suppose Sales is reported quarterly, but Profit and Costs twice yearly.
Example
This allows the higher frequency Sales data to be used with the less frequent Profit and Costs data!
Example
Australian GDP is calculated with 3 approaches:
For simplicity consider a small part of these graphs. The complete graph structure has many more disaggregates.
This example is used in Athanasopoulos et al. (2020).
If the bottom level is too sparse, it is more complicated to model and reconciliation can worsen forecast accuracy.
What if the coherency structure doesn’t completely aggregate, so that there are multiple top series.
This can occur for many reasons:
It makes no sense to aggregate folds of cross-validation.
A suitable DAG for cross-validated hierarchies is
Each disjoint graph can be reconciled separately.
Motivated by discussion with Zeynepz yesterday
Adding Meta as the single parent results in a hierarchy
Note that this isn’t a polytree, due to common/shared leafs.
General linearly constrained time series (Girolimetto and Di Fonzo 2023)
Generalisation from zero-constrained representation


For linear reconciliation, both graph coherence and ‘general linearly constrained’ coherence are equivalent.

All currently experimental, but functional. Code on GitHub in various branches.
Useful functions
aggregate_key() aggregate_index() for temporal)agg_vec() and graph_vec() for complex aggregation structures and graphs.reconcile() and min_trace()Planned functionality
# A tsibble: 24,320 x 5 [1Q]
# Key: Region, State, Purpose [304]
Quarter Region State Purpose Trips
<qtr> <chr> <chr> <chr> <dbl>
1 1998 Q1 Adelaide South Australia Business 135.
2 1998 Q2 Adelaide South Australia Business 110.
3 1998 Q3 Adelaide South Australia Business 166.
4 1998 Q4 Adelaide South Australia Business 127.
5 1999 Q1 Adelaide South Australia Business 137.
6 1999 Q2 Adelaide South Australia Business 200.
7 1999 Q3 Adelaide South Australia Business 169.
8 1999 Q4 Adelaide South Australia Business 134.
9 2000 Q1 Adelaide South Australia Business 154.
10 2000 Q2 Adelaide South Australia Business 169.
# i 24,310 more rows
# A tsibble: 34,000 x 5 [1Q]
# Key: Purpose, State, Region [425]
Quarter Purpose State Region Trips
<qtr> <chr*> <chr*> <chr*> <dbl>
1 1998 Q1 <aggregated> <aggregated> <aggregated> 23182.
2 1998 Q2 <aggregated> <aggregated> <aggregated> 20323.
3 1998 Q3 <aggregated> <aggregated> <aggregated> 19827.
4 1998 Q4 <aggregated> <aggregated> <aggregated> 20830.
5 1999 Q1 <aggregated> <aggregated> <aggregated> 22087.
6 1999 Q2 <aggregated> <aggregated> <aggregated> 21458.
7 1999 Q3 <aggregated> <aggregated> <aggregated> 19914.
8 1999 Q4 <aggregated> <aggregated> <aggregated> 20028.
9 2000 Q1 <aggregated> <aggregated> <aggregated> 22339.
10 2000 Q2 <aggregated> <aggregated> <aggregated> 19941.
# i 33,990 more rows
# A tibble: 425 x 4
Purpose State Region .rows
<chr*> <chr*> <chr*> <lis>
1 Business ACT Canberra [80]
2 Business ACT <aggregated> [80]
3 Business New South Wales Blue Mountains [80]
4 Business New South Wales Capital Country [80]
5 Business New South Wales Central Coast [80]
6 Business New South Wales Central NSW [80]
7 Business New South Wales Hunter [80]
8 Business New South Wales New England North West [80]
9 Business New South Wales North Coast NSW [80]
10 Business New South Wales Outback NSW [80]
# i 415 more rows
# A tibble: 45 x 3
Purpose State .rows
<chr*> <chr*> <list<int>>
1 Business ACT [80]
2 Business New South Wales [80]
3 Business Northern Territory [80]
4 Business Queensland [80]
5 Business South Australia [80]
6 Business Tasmania [80]
7 Business Victoria [80]
8 Business Western Australia [80]
9 Business <aggregated> [80]
10 Holiday ACT [80]
11 Holiday New South Wales [80]
12 Holiday Northern Territory [80]
13 Holiday Queensland [80]
14 Holiday South Australia [80]
15 Holiday Tasmania [80]
16 Holiday Victoria [80]
17 Holiday Western Australia [80]
18 Holiday <aggregated> [80]
19 Other ACT [80]
20 Other New South Wales [80]
21 Other Northern Territory [80]
22 Other Queensland [80]
23 Other South Australia [80]
24 Other Tasmania [80]
25 Other Victoria [80]
26 Other Western Australia [80]
27 Other <aggregated> [80]
28 Visiting ACT [80]
29 Visiting New South Wales [80]
30 Visiting Northern Territory [80]
31 Visiting Queensland [80]
32 Visiting South Australia [80]
33 Visiting Tasmania [80]
34 Visiting Victoria [80]
35 Visiting Western Australia [80]
36 Visiting <aggregated> [80]
37 <aggregated> ACT [80]
38 <aggregated> New South Wales [80]
39 <aggregated> Northern Territory [80]
40 <aggregated> Queensland [80]
41 <aggregated> South Australia [80]
42 <aggregated> Tasmania [80]
43 <aggregated> Victoria [80]
44 <aggregated> Western Australia [80]
45 <aggregated> <aggregated> [80]
# A tibble: 33 x 3
Purpose State .rows
<chr*> <chr*> <list<int>>
1 Business ACT [80]
2 Business New South Wales [80]
3 Business Northern Territory [80]
4 Business Queensland [80]
5 Business South Australia [80]
6 Business Tasmania [80]
7 Business Victoria [80]
8 Business Western Australia [80]
9 Holiday ACT [80]
10 Holiday New South Wales [80]
11 Holiday Northern Territory [80]
12 Holiday Queensland [80]
13 Holiday South Australia [80]
14 Holiday Tasmania [80]
15 Holiday Victoria [80]
16 Holiday Western Australia [80]
17 Other ACT [80]
18 Other New South Wales [80]
19 Other Northern Territory [80]
20 Other Queensland [80]
21 Other South Australia [80]
22 Other Tasmania [80]
23 Other Victoria [80]
24 Other Western Australia [80]
25 Visiting ACT [80]
26 Visiting New South Wales [80]
27 Visiting Northern Territory [80]
28 Visiting Queensland [80]
29 Visiting South Australia [80]
30 Visiting Tasmania [80]
31 Visiting Victoria [80]
32 Visiting Western Australia [80]
33 <aggregated> <aggregated> [80]
# A tibble: 13 x 3
Purpose State .rows
<chr*> <chr*> <list<int>>
1 Business <aggregated> [80]
2 Holiday <aggregated> [80]
3 Other <aggregated> [80]
4 Visiting <aggregated> [80]
5 <aggregated> ACT [80]
6 <aggregated> New South Wales [80]
7 <aggregated> Northern Territory [80]
8 <aggregated> Queensland [80]
9 <aggregated> South Australia [80]
10 <aggregated> Tasmania [80]
11 <aggregated> Victoria [80]
12 <aggregated> Western Australia [80]
13 <aggregated> <aggregated> [80]
# A tibble: 12 x 3
Purpose State .rows
<chr*> <chr*> <list<int>>
1 Business <aggregated> [80]
2 Holiday <aggregated> [80]
3 Other <aggregated> [80]
4 Visiting <aggregated> [80]
5 <aggregated> ACT [80]
6 <aggregated> New South Wales [80]
7 <aggregated> Northern Territory [80]
8 <aggregated> Queensland [80]
9 <aggregated> South Australia [80]
10 <aggregated> Tasmania [80]
11 <aggregated> Victoria [80]
12 <aggregated> Western Australia [80]
tourism |>
aggregate_key(
Purpose,
Trips = sum(Trips)
) |>
stretch_tsibble(.step = 4, .init = 60) |>
key_data()# A tibble: 30 x 3
.id Purpose .rows
<int> <chr*> <list<int>>
1 1 Business [60]
2 1 Holiday [60]
3 1 Other [60]
4 1 Visiting [60]
5 1 <aggregated> [60]
6 2 Business [64]
7 2 Holiday [64]
8 2 Other [64]
9 2 Visiting [64]
10 2 <aggregated> [64]
11 3 Business [68]
12 3 Holiday [68]
13 3 Other [68]
14 3 Visiting [68]
15 3 <aggregated> [68]
16 4 Business [72]
17 4 Holiday [72]
18 4 Other [72]
19 4 Visiting [72]
20 4 <aggregated> [72]
21 5 Business [76]
22 5 Holiday [76]
23 5 Other [76]
24 5 Visiting [76]
25 5 <aggregated> [76]
26 6 Business [80]
27 6 Holiday [80]
28 6 Other [80]
29 6 Visiting [80]
30 6 <aggregated> [80]
tourism |>
aggregate_key(
Purpose,
Trips = sum(Trips)
) |>
stretch_tsibble(.step = 4, .init = 60) |>
model(ets = ETS(Trips)) |>
reconcile(ets_coherent = min_trace(ets)) |>
forecast(h = "1 year")# A fable: 240 x 6 [1Q]
# Key: .id, Purpose, .model [60]
.id Purpose .model Quarter Trips
<int> <chr*> <chr> <qtr> <dist>
1 1 Business ets 2013 Q1 N(3135, 46032)
2 1 Business ets 2013 Q2 N(3832, 73712)
3 1 Business ets 2013 Q3 N(4158, 93320)
4 1 Business ets 2013 Q4 N(3781, 88006)
5 1 Business ets_coherent 2013 Q1 N(3159, 45373)
6 1 Business ets_coherent 2013 Q2 N(3848, 69353)
7 1 Business ets_coherent 2013 Q3 N(4177, 86871)
8 1 Business ets_coherent 2013 Q4 N(3795, 83437)
9 1 Holiday ets 2013 Q1 N(10442, 211377)
10 1 Holiday ets 2013 Q2 N(8698, 146661)
# i 230 more rows
# i 1 more variable: .mean <dbl>


Coherence and graph theory
DAGs are a useful tool for representing structured time series and producing coherent forecasts.

Coherence and graph theory
DAGs are a useful tool for representing structured time series and producing coherent forecasts.


Other benefits
Future work
Final remarks

Thanks to these Unsplash contributors for their photos