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.
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