fable
fable copied to clipboard
ARIMA will not produce a weekly forecast when week_start != 1
See reprex below. If week_start is set to 1 (the default) everything works as expected.
library(fable)
#> Loading required package: fabletools
library(tsibble)
#>
#> Attaching package: 'tsibble'
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, union
dat<-tsibble(wk=make_yearweek(2023, 21:50, week_start=7),
x=rnorm(30,100,10),
index=wk)
mable <- model(dat, ARIMA(x ~ pdq()))
fable <- mable %>% forecast(h=3)
#> Error in `mutate()`:
#> ℹ In argument: `ARIMA(x ~ pdq()) = (function (object, ...) ...`.
#> Caused by error in `vec_ptype2.yearweek.yearweek()`:
#> ! Can't combine <yearweek> with different `week_start`.
#> Backtrace:
#> ▆
#> 1. ├─mable %>% forecast(h = 3)
#> 2. ├─generics::forecast(., h = 3)
#> 3. ├─fabletools:::forecast.mdl_df(., h = 3)
#> 4. │ └─dplyr::mutate_at(...)
#> 5. │ ├─dplyr::mutate(.tbl, !!!funs)
#> 6. │ └─dplyr:::mutate.data.frame(.tbl, !!!funs)
#> 7. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), by)
#> 8. │ ├─base::withCallingHandlers(...)
#> 9. │ └─dplyr:::mutate_col(dots[[i]], data, mask, new_columns)
#> 10. │ └─mask$eval_all_mutate(quo)
#> 11. │ └─dplyr (local) eval()
#> 12. ├─generics (local) `<fn>`(...)
#> 13. └─fabletools:::forecast.lst_mdl(...)
#> 14. └─fabletools:::mapply_maybe_parallel(...)
#> 15. └─base::mapply(FUN = .f, ..., MoreArgs = MoreArgs, SIMPLIFY = SIMPLIFY)
#> 16. ├─generics (local) `<fn>`(dots[[1L]][[1L]], dots[[2L]][[1L]], h = 3, point_forecast = `<named list>`)
#> 17. └─fabletools:::forecast.mdl_ts(...)
#> 18. ├─generics::forecast(...)
#> 19. └─fable:::forecast.ARIMA(...)
#> 20. └─vctrs:::`!=.vctrs_vctr`(...)
#> 21. └─vctrs::vec_equal(e1, e2)
#> 22. └─vctrs:::vec_cast_common_params(!!!args, .to = .ptype)
#> 23. └─vctrs:::vec_cast_common_opts(...)
#> 24. └─vctrs (local) `<fn>`()
#> 25. └─tsibble:::vec_ptype2.yearweek.yearweek(x = x, y = y, x_arg = x_arg, y_arg = y_arg, call = call)
#> 26. └─rlang::abort("Can't combine <yearweek> with different `week_start`.")
new_data <- tsibble(wk=make_yearweek(2023, 51:52, week_start=7), index=wk)
fable <- mable %>% forecast(new_data = new_data)
#> Error in `mutate()`:
#> ℹ In argument: `ARIMA(x ~ pdq()) = (function (object, ...) ...`.
#> Caused by error in `vec_ptype2.yearweek.yearweek()`:
#> ! Can't combine <yearweek> with different `week_start`.
#> Backtrace:
#> ▆
#> 1. ├─mable %>% forecast(new_data = new_data)
#> 2. ├─generics::forecast(., new_data = new_data)
#> 3. ├─fabletools:::forecast.mdl_df(., new_data = new_data)
#> 4. │ └─dplyr::mutate_at(...)
#> 5. │ ├─dplyr::mutate(.tbl, !!!funs)
#> 6. │ └─dplyr:::mutate.data.frame(.tbl, !!!funs)
#> 7. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), by)
#> 8. │ ├─base::withCallingHandlers(...)
#> 9. │ └─dplyr:::mutate_col(dots[[i]], data, mask, new_columns)
#> 10. │ └─mask$eval_all_mutate(quo)
#> 11. │ └─dplyr (local) eval()
#> 12. ├─generics (local) `<fn>`(...)
#> 13. └─fabletools:::forecast.lst_mdl(...)
#> 14. └─fabletools:::mapply_maybe_parallel(...)
#> 15. └─base::mapply(FUN = .f, ..., MoreArgs = MoreArgs, SIMPLIFY = SIMPLIFY)
#> 16. ├─generics (local) `<fn>`(dots[[1L]][[1L]], dots[[2L]][[1L]], h = NULL, point_forecast = `<named list>`)
#> 17. └─fabletools:::forecast.mdl_ts(...)
#> 18. ├─generics::forecast(...)
#> 19. └─fable:::forecast.ARIMA(...)
#> 20. └─vctrs:::`!=.vctrs_vctr`(...)
#> 21. └─vctrs::vec_equal(e1, e2)
#> 22. └─vctrs:::vec_cast_common_params(!!!args, .to = .ptype)
#> 23. └─vctrs:::vec_cast_common_opts(...)
#> 24. └─vctrs (local) `<fn>`()
#> 25. └─tsibble:::vec_ptype2.yearweek.yearweek(x = x, y = y, x_arg = x_arg, y_arg = y_arg, call = call)
#> 26. └─rlang::abort("Can't combine <yearweek> with different `week_start`.")
Possibly related? https://github.com/tidyverts/tsibble/issues/299
I looked into this a little bit, and the problem comes when the arima model object is created. It has a $tsp which has a $range, where the week_start hasn't been propagated. So the problem appears to be in whatever happens inside range() when a vector of yearweeks are given.
library(fable)
#> Loading required package: fabletools
library(tsibble)
#>
#> Attaching package: 'tsibble'
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, union
dat<-tsibble(wk=make_yearweek(2023, 21:50, week_start=7),
x=rnorm(30,100,10),
index=wk)
dat$wk[1]
#> <yearweek[1]>
#> [1] "2023 W21"
#> # Week starts on: Sunday
range(dat$wk)
#> <yearweek[2]>
#> [1] "2023 W20" "2023 W49"
#> # Week starts on: Monday
I think range just does something like c(min(dat$wk), max(dat$wk))
, without propagating the attributes of the object.
The code that makes the range at L402 of arima.R needs to be aware of yearweek objects. The right thing might be to make a range() that knows how to operate properly on yearweeks.
Putting this in my code appears to paper over the problem:
range.yearweek <- function(x, ...) {
yearweek(c(min(x), max(x)), week_start=attr(x, "week_start"))
}
I don't know how to write that code properly or I'd submit a PR.
Thanks for your careful investigation, resolving https://github.com/tidyverts/tsibble/issues/300 should fix this issue.