Using the hts package in R, how to reconcile hierarchical forecasts (using non-standard models)

I am working with the hts package in R - I have several groups of hierarchical forecasts which I need to reconcile. However, I am working with a non-standard forecasting model, so am unable to estimate the model/forecast using the in-built functions in this package. As a result, I am unsure how to implement this in R - I have forecasts for each of my nodes and the aggregations but I don't know how to input this (or if it's even possible).

I have managed to convert my forecasts into a ts matrix, but several of the columns are aggregates. As a result, I don't know how to convert this into a gts matrix, as the grouping input doesn't seem to have an option for this.

My current forecasts look something like this and I would like to be able to reconcile them using MinT:

forecasts <- rbind(c(1,1,1,1,2,3,3,4,6),c(1,1,2,1,3,4,3,2,7),c(0,1,0,1,3,2,2,3,6))
rownames(forecasts) <- c("2010","2011","2012")
colnames(forecasts) <- c("uk_internal","eu_internal","uk_external","eu_external","uk_total","eu_total","total_external","total_internal","total_total")
ts(forecasts)

The hts package has mostly been superceded by the fable package, which provides much easier handling of different aggregation structures.

To use hts, you need to reorder the forecasts into the order hts expects. Like this:

library(hts)

forecasts <- rbind(c(1,1,1,1,2,3,3,4,6),c(1,1,2,1,3,4,3,2,7),c(0,1,0,1,3,2,2,3,6))
rownames(forecasts) <- c("2010","2011","2012")
colnames(forecasts) <- c("uk_internal","eu_internal","uk_external","eu_external","uk_total","eu_total","total_external","total_internal","total_total")
forecasts <- ts(forecasts)

# Construct groups matrix
gps <- gts(forecasts[,1:4], characters = c(3,8))$groups
#> Argument gnames is missing and the default labels are used.

# Reorder forecasts to satisfy hts requirements
forecasts <- forecasts[,c(9,5,6,8,7,1:4)]

# Reconcile forecasts
reconciled <- combinef(forecasts, groups = gps) |> aggts()
colnames(reconciled) <- colnames(forecasts)

forecasts
#> Time Series:
#> Start = 1 
#> End = 3 
#> Frequency = 1 
#>   total_total uk_total eu_total total_internal total_external uk_internal
#> 1           6        2        3              4              3           1
#> 2           7        3        4              2              3           1
#> 3           6        3        2              3              2           0
#>   eu_internal uk_external eu_external
#> 1           1           1           1
#> 2           1           2           1
#> 3           1           0           1
reconciled
#> Time Series:
#> Start = 1 
#> End = 3 
#> Frequency = 1 
#>   total_total uk_total eu_total total_internal total_external uk_internal
#> 1    5.777778 2.555556 3.222222       3.222222       2.555556    1.444444
#> 2    6.333333 3.000000 3.333333       2.666667       3.666667    1.000000
#> 3    5.111111 2.555556 2.555556       2.888889       2.222222    1.444444
#>   eu_internal uk_external eu_external
#> 1    1.777778    1.111111    1.444444
#> 2    1.666667    2.000000    1.666667
#> 3    1.444444    1.111111    1.111111

Created on 2025-01-26 with reprex v2.1.1

Thank you, that's really helpful! I was attempting to use fable initially, but couldn't work out a way of converting my forecasts into the necessary format there either - what would be the approach for reconciling using fable with the same data:

forecasts <- rbind(c(1,1,1,1,2,3,3,4,6),c(1,1,2,1,3,4,3,2,7),c(0,1,0,1,3,2,2,3,6))
rownames(forecasts) <- c("2010","2011","2012")
colnames(forecasts) <- c("uk_internal","eu_internal","uk_external","eu_external","uk_total","eu_total","total_external","total_internal","total_total")

It's tricky to do this in fable as reconciliation is applied to the model object before the forecasting step, rather than as a post-forecasting step. You would have to write your forecast method as a function that can be called within model().