Hierarchical time series are time series that can be divided into sub-series. In persephone, such objects are created similar to a nested list. The following example creates a series with two subseries a and b

library(persephone)
hts <- perHts(
  a = perX13(AirPassengers),
  b = perTramo(AirPassengers)
)
hts
#>  component run   class                 
#>            FALSE hierarchicalTimeSeries
#>  a         FALSE x13Single             
#>  b         FALSE tramoseatsSingle

If the run() method of hts is invoked, the following adjustments will be made

  • the aggregate series a+b is adjusted and the results are saved in hts$output.
  • a is adjusted with x13()
  • b is adjusted with tramoseats()

The results can be viewed as follows

display_result <- function(ts) {
  window(ts, end = c(1949, 6))
}
hts$run()
display_result(hts$adjusted)
#> Warning in (function () : The decision between direct and indirect adjustment was not recorded yet. 
#> Direct adjustment is returned.
#>           Jan      Feb      Mar      Apr      May      Jun
#> 1949 245.3656 249.3203 250.2444 254.9434 254.7441 252.3840
display_result(hts$components$a$adjusted)
#>           Jan      Feb      Mar      Apr      May      Jun
#> 1949 123.7166 125.2532 125.9332 128.1540 129.0103 126.8570
display_result(hts$adjustedIndirect)
#>           Jan      Feb      Mar      Apr      May      Jun
#> 1949 246.3994 249.9133 251.0553 255.6256 256.3824 253.0490

The last line displays the results of an indirect adjustment which amounts to a$adjusted + b$adjusted in this case.

Several levels of hierarchies

In case more hierarchy levels are introduced, the calls to perHts can be nested.

hts_nested <- perHts(
  hts = hts,
  hts_child = perHts(
    a = perX13(AirPassengers)
  ),
  b = perTramo(AirPassengers)
)
hts_nested
#>  component   run   class                  seasonality logTransform
#>              FALSE hierarchicalTimeSeries <NA>          NA        
#>  hts          TRUE hierarchicalTimeSeries Present     TRUE        
#>  hts/a        TRUE x13Single              Present     TRUE        
#>  hts/b        TRUE tramoseatsSingle       Present     TRUE        
#>  hts_child   FALSE hierarchicalTimeSeries <NA>          NA        
#>  hts_child/a FALSE x13Single              <NA>          NA        
#>  b           FALSE tramoseatsSingle       <NA>          NA        
#>  arimaMdl       nOutliers qStat
#>  <NA>           NA          NA 
#>  (0 1 0)(0 1 1)  2          NA 
#>  (0 1 0)(0 1 1)  1        0.22 
#>  (0 1 0)(0 1 1)  2          NA 
#>  <NA>           NA          NA 
#>  <NA>           NA          NA 
#>  <NA>           NA          NA

As we can see, the runs of hts are available to this object.

Iterating over the hierarchy tree

To iterate over all components of a perHts object, the iterate method can be used. It baehaves similar to lapply.

hts_nested$run()
hts_nested$iterate(asTable = TRUE, function(obj) {
  list(mean = mean(obj$adjusted),
       var = sd(obj$adjusted))
})
#>     component      mean      var
#> 1             1120.0985 444.2033
#> 2         hts  560.0492 222.1017
#> 3       hts/a  280.0419 111.5113
#> 4       hts/b  280.0246 111.0508
#> 5   hts_child  280.0246 111.0508
#> 6 hts_child/a  280.0419 111.5113
#> 7           b  280.0246 111.0508
hts_nested$iterate(asTable = TRUE, persephone:::generateQrList)[, 1:9]
#>     component Method Period Nobs  Start     End Log.Transformation
#> 1                 TS     12  144 1-1949 12-1960               TRUE
#> 2         hts     TS     12  144 1-1949 12-1960               TRUE
#> 3       hts/a    x13     12  144 1-1949 12-1960               TRUE
#> 4       hts/b     TS     12  144 1-1949 12-1960               TRUE
#> 5   hts_child     TS     12  144 1-1949 12-1960               TRUE
#> 6 hts_child/a    x13     12  144 1-1949 12-1960               TRUE
#> 7           b     TS     12  144 1-1949 12-1960               TRUE
#>      ARIMA.Model LeapYear
#> 1 (0 1 0)(0 1 1)     TRUE
#> 2 (0 1 0)(0 1 1)     TRUE
#> 3 (0 1 0)(0 1 1)    FALSE
#> 4 (0 1 0)(0 1 1)     TRUE
#> 5 (0 1 0)(0 1 1)     TRUE
#> 6 (0 1 0)(0 1 1)    FALSE
#> 7 (0 1 0)(0 1 1)     TRUE

setting options recursively

hts_nested$setOptions(spec = "RSA1", recursive = TRUE)

get_spec <- function(x) {
  list(spec = x$spec)
}

## check if options where applied correctly
hts_nested$iterate(asTable = TRUE, get_spec)
#>     component spec
#> 1             RSA1
#> 2         hts RSA1
#> 3       hts/a RSA1
#> 4       hts/b RSA1
#> 5   hts_child RSA1
#> 6 hts_child/a RSA1
#> 7           b RSA1

## modify options beginning from hts
hts$setOptions(spec = "RSA0", recursive = TRUE)
hts_nested$iterate(asTable = TRUE, get_spec)
#>     component spec
#> 1             RSA1
#> 2         hts RSA1
#> 3       hts/a RSA0
#> 4       hts/b RSA0
#> 5   hts_child RSA1
#> 6 hts_child/a RSA1
#> 7           b RSA1