1

I'm following Dr. Rob Hyndman's textbook on time series forecasting in R. I'm in Chapter 13 which talks about Practical Forecasting Issues (and I'm having issues while working through the practical forecasting issue section!)

Specifically, I'm trying to create a combination forecast, but the code that creates a linear function of the estimated models coerces my tsibble to a tibble, whereas without that line of code I would end up with a mable, and I can't seem to work the tibble back into a mable.

Here is Dr. Hyndman's code:

auscafe <- aus_retail %>%
  filter(stringr::str_detect(Industry, "Takeaway")) %>%
  summarise(Turnover = sum(Turnover))

train <- auscafe %>%
  filter(year(Month) <= 2013)

STLF <- decomposition_model(
  STL(log(Turnover) ~ season(window = Inf)),
  ETS(season_adjust ~ season("N"))
)

cafe_models <- train %>%
  model(
    ets = ETS(Turnover),
    stlf = STLF,
    arima = ARIMA(log(Turnover))
  ) %>%
  mutate(combination = (ets + stlf + arima) / 3)

cafe_fc <- cafe_models %>% 
forecast(h = "5 years")

But when I try it out in my own console I'm not having luck.

Hyndman's dataframe exists in the fable or fabletools or feasts or tsibble or tsibbledata packages. (I can't remember which one.)

Here is my dataframe:

structure(list(Date = structure(c(19114, 19115, 19116, 19117, 
19118, 19119, 19120, 19121, 19122, 19123, 19124, 19125, 19126, 
19127, 19128, 19129, 19130, 19131, 19132, 19133, 19134, 19135, 
19136, 19137, 19138, 19139, 19140, 19141, 19142, 19143, 19144, 
19145, 19146, 19147, 19148, 19149, 19150, 19151, 19152, 19153, 
19154, 19155, 19156, 19157, 19158, 19159, 19160, 19161, 19162, 
19163, 19164, 19165), class = "Date"), Sales = c(2147350, 1953453, 
1930514, 1951737, 2496552, 2091370, 1921364, 2342280, 2224779, 
2124766, 2229922, 2501654, 2056751, 1908814, 2109249, 1946929, 
2057711, 2001398, 2535514, 2060774, 1793765, 1954603, 2019082, 
2077929, 2152838, 2802181, 2314866, 2268680, 2380746, 1887751, 
2201204, 2004422, 2783170, 2238542, 2000024, 1777258, 1844045, 
2138638, 2387784, 2783170, 1988945, 1749007, 2128774, 2101340, 
2122877, 2085712, 2532569, 1995143, 1713529, 2045398, 1781901, 
2164901)), class = c("tbl_ts", "tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-52L), key = structure(list(.rows = structure(list(1:52), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -1L)), index = structure("Date", ordered = TRUE), index2 = "Date", interval = structure(list(
    year = 0, quarter = 0, month = 0, week = 0, day = 1, hour = 0, 
    minute = 0, second = 0, millisecond = 0, microsecond = 0, 
    nanosecond = 0, unit = 0), .regular = TRUE, class = c("interval", 
"vctrs_rcrd", "vctrs_vctr")))

And here is my code:

library(tsibble)
library(tsibbledata)
library(fable)
library(fabletools)
library(feasts)

my_dcmp_spec <- decomposition_model(
  STL(Sales),
  ETS(season_adjust ~ season("N"))
)

fit <- time_series_sample %>%
  model(
    stl_ets = my_dcmp_spec,
    `Seasonal naïve` = SNAIVE(Sales),
    holt_winters = ETS(Sales ~ error("A") + trend("N") + season("N"))
  ) %>%
    mutate(combination = (stl_ets + `Seasonal naïve` + holt_winters) / 3) 

This final bit I can't recreate.

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

Here is the error message I receive.

Error in UseMethod("forecast") : 
  no applicable method for 'forecast' applied to an object of class "c('tbl_df', 'tbl', 'data.frame')"

So I tried again using this function to coerce the tibble to a mable:

fit %>% as_mable()

I get another error message:

Error in `build_mable()`:
! A mable must contain at least one model.
Backtrace:
 1. fit %>% as_mable()
 3. fabletools:::as_mable.data.frame(.)
 4. fabletools:::build_mable(x, key = !!enquo(key), model = !!enquo(model))

This error message doesn't make sense to me because my tibble does contain models, as you can see in the screenshot.

enter image description here

I also tried adding pivot_longer both with and without the as_mable() call, but that doesn't work either.

fit <- time_series_sample %>%
  model(
    stl_ets = my_dcmp_spec,
    `Seasonal naïve` = SNAIVE(Sales),
    holt_winters = ETS(Sales ~ error("A") + trend("N") + season("N"))
  ) %>%
    mutate(combination = (stl_ets + `Seasonal naïve` + holt_winters) / 3) %>%
  pivot_longer(everything(), names_to = "Model name",
                     values_to = "Sales") 
# as_mable()

As long as I include the step where I create a combination model, which is the mutate(combination(... line, I end up with a tibble and not a mable.

Dr. Hyndman's code doesn't seem to coerce his models into a tibble, but keeps them as a mable, while my code seems to coerce to a tibble. What can I do to fix this?

If I run the code without the combination part, I can get this graph

fit <- time_series_sample %>%
  model(
    stl_ets = my_dcmp_spec,
    seasonal_naive = SNAIVE(Sales),
    holt_winters = ETS(Sales ~ error("A") + trend("N") + season("N"))
  ) 

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

fc %>% autoplot(time_series_sample) 

But I'm definitely missing the combination forecast, which is what I'm really hoping to add.

Is all this a bug? The mutate works to create the combination forecast, which is a linear combination of models - I can see that it worked because I see an S3: lst_model in the cell... but the mable is coerced to a tibble and I can't use forecast on it

enter image description here

hachiko
  • 671
  • 7
  • 20
  • 1
    How have you defined `my_dcmp_spec` ? That part is not included in your code. If I remove this from the model part of your code (`fit <- ...`) your code returns a mable and I can do a forecast. – phiver Jun 23 '22 at 07:20
  • I included the code for my_dcmp_spec I apologize I left it off my_dcmp_spec <- decomposition_model( STL(Sales), ETS(season_adjust ~ season("N")) ) – hachiko Jun 23 '22 at 07:45
  • I guess I'm unsure on your comment. Isn't the fit <- just saving the result as a tibble (or hopefully, mable)? – hachiko Jun 23 '22 at 07:52
  • 1
    I tried the code based on your example and code, and the `fit` returns a `mable` and I can make a forecast without any issues. Can you check if you don't have another package loaded that overwrites `dplyr::mutate` ? – phiver Jun 23 '22 at 07:57
  • hm I don't know how to check other packages I have loaded for conflicts. I type ?mutate and see two options the help, one for dplyr and one for plyr, but I think that's just like reading the documentation. I tried the code again while explicitly calling dplyr::mutate just in case, and it didn't work for me. – hachiko Jun 23 '22 at 08:04
  • I just restarted RStudio and made sure the only packages loaded were tidyverse, lubridate, fabe, feasts, and tsibble, so I don't think it's a conflict with mutate, although I agree the error is happening there – hachiko Jun 23 '22 at 08:18
  • What happens when you run the code from the textbook? Or just load fpp3. It will load all the necessary packages without loading all the tidyverse packages. – phiver Jun 23 '22 at 09:59
  • I tried running the code only using library(fpp3). My code fails at the same point with the error about tibble. And the code from the textbook also fails at the same point. Maybe there's an updated method for how combination forecasts are calculated, since this version of the book was written? – hachiko Jun 23 '22 at 12:59
  • 1
    You might want to check / update all your packages. I don't have any issue with any part of the code from the book or yours. – phiver Jun 23 '22 at 14:11
  • 2
    It actually wasn't the packages at all; I had to download a newer version of RStudio and now I can get the code to work as expected. Thanks for all your help and troubleshooting. I'm a little surprised that the behavior was different for a specific package in this way because the RStudio IDE version needed to be updated – hachiko Jun 23 '22 at 17:19

0 Answers0