Calculating a weighted average of ARIMA forecasts and putting it into a fanchart in fable package

I have the following dataframe, which I've used to build an ARIMA model and forecasts, before plotting it in a fanchart using the fable package.

I'm hoping to find a solution in which I can fit my ARIMA forecasts for multiple variables (Component 1 and 2), where for example each variable is weighted equally (50% each) in my forecasts. Is there any way to do this and plot my fanchart with these weighted forecasts? My example below has only run an ARIMA forecast on one of the variables (Component 1), but I'm hoping to run an ARIMA forecasts on all of my variables and weight them accordingly

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

data <- structure(list(Date = structure(c(18383, 18414, 18444, 18475, 
18506, 18536, 18567, 18597, 18628, 18659, 18687, 18718, 18748
), class = c("yearmonth", "vctrs_vctr")), `Component 1` = c(-0.136535845906039, 
-0.836519457510263, -1.18729738867468, 1.15910388651122, 1.2562958338269, 
-1.19066468349899, -1.21838083407816, -1.34198585493321, -0.843625520768398, 
0.192071067785477, 2.43893315702964, 7.53338782924422, 7.31128441509166
), `Component 2` = c(2.16292504382349, 3.61278939509646, 4.46165448523277, 
3.64200206159624, 3.77062926096379, 4.26941270942491, 4.58011851783391, 
4.2695187122175, 4.96351398840244, 4.16536909803045, 3.78233085059824, 
4.2340896479389, 3.48259766258533)), row.names = c(NA, -13L), key = structure(list(
    .rows = structure(list(1:13), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame")), index = structure("Date", ordered = TRUE), index2 = "Date", interval = structure(list(
    year = 0, quarter = 0, month = 1, week = 0, day = 0, hour = 0, 
    minute = 0, second = 0, millisecond = 0, microsecond = 0, 
    nanosecond = 0, unit = 0), .regular = TRUE, class = c("interval", 
"vctrs_rcrd", "vctrs_vctr")), class = c("tbl_ts", "tbl_df", "tbl", 
"data.frame"))

arima_model <- data %>% model(arima = ARIMA(`Component 1`))

forecasts <- arima_model %>% 
             forecast(h = '6 months')

fanchart <- autoplot(forecasts, level = seq(10, 90, by = 10))

fanchart


What's your motivation for the weighting?

If there's a third variable to want to forecast other than Component 1 and Component 2, you might want to fit a forecast model for it explicitly rather than describe it as weighted average of Component 1 and Component 2 without any fitting.

@arthur.t so I have a bunch of different variables that are sub-indices for a broader index (such as all of the different components that make up the Consumer Price Index). My aim is to ultimately have a fan chart which illustrates my forecasts as a weighted combination of all of the sub-indices I have, so I can contrast that with an ARIMA forecast run explicitly on the broader index that I have. Hope that makes sense?

I see. I guess you could use the fitted values of the arima models on past data of Component 1 and 2 as predictors for the broader index with a lm model. You'd have to coerce them to numeric and put in a data frame.

arima doesn't seem to give you fitted values for some reason, but Arima and auto.arima do.

You can then predict with the lm model on the forecasts of Component 1 and Component 2.

You can combine models using a forecast combination model - Combination modelling — combination_model • fabletools

Creating a fan chart (a forecast interval plot with many intervals) is possible in fable by simply specifying more intervals you wish to plot:

library(fpp3)
#> ── Attaching packages ──────────────────────────────────────────── fpp3 0.4.0 ──
#> ✓ tibble      3.1.2          ✓ tsibble     1.0.1     
#> ✓ dplyr       1.0.6          ✓ tsibbledata 0.3.0     
#> ✓ tidyr       1.1.3          ✓ feasts      0.2.1.9000
#> ✓ lubridate   1.7.10         ✓ fable       0.3.1     
#> ✓ ggplot2     3.3.3.9000
#> ── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
#> x lubridate::date()    masks base::date()
#> x dplyr::filter()      masks stats::filter()
#> x tsibble::intersect() masks base::intersect()
#> x tsibble::interval()  masks lubridate::interval()
#> x dplyr::lag()         masks stats::lag()
#> x tsibble::setdiff()   masks base::setdiff()
#> x tsibble::union()     masks base::union()
accidental_deaths <- as_tsibble(USAccDeaths)
accidental_deaths %>% 
  model(ETS(value)) %>% 
  forecast() %>% 
  autoplot(accidental_deaths, level = seq(50, 95, by = 5))

Created on 2021-07-15 by the reprex package (v2.0.0)

1 Like

Thanks so much @mitchelloharawild , this looks like a great solution! Just a quick question, is it possible to specify a vector of weights in the cmbn_args function within a combination_model ? I see that the default option is an equal weighted model, however I'm just curious to know whether I can manually specify the weights if I wanted to run a model that's not equally weighted?

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.