tidyverts / fabletools

General fable features useful for extension packages
http://fabletools.tidyverts.org/
89 stars 31 forks source link

Reconciliation raises an unexpected error #358

Open mitchelloharawild opened 2 years ago

mitchelloharawild commented 2 years ago

First, this has nothing to do with the hts package. You are using the forecast reconcilation procedures in the fabletools package.

Second, your example consists of a single time series (the ACT), so the reconciliation is degenerate.

Third, SNAIVE is already reconciled since the forecasts are equal to the last year of data, so the reconciliation is degenerate.

That said, we should improve fabletools to prevent the error. @mitchelloharawild

To see it working on a small non-degenerate example, try this:

library(dplyr  , quietly = TRUE)
library(tsibble, quietly = TRUE)
library(fable  , quietly = TRUE)

tsibble::tourism %>%
  filter(State == 'ACT') %>% 
  aggregate_key(State / Region, Trips = sum(Trips)) %>% 
  model(base = fable::SNAIVE(Trips)) %>%
  reconcile(mint_cov = min_trace(base, method = "mint_cov")) %>% 
  forecast(h = 1)

From https://github.com/earowang/hts/issues/43#issuecomment-1139303691

MattCowgill commented 1 year ago

I'm encountering this problem even with @robjhyndman's example code provided above (via https://github.com/earowang/hts/issues/43#issuecomment-1139303691).

I've tried downgrading from fabletools 0.3.3.900 to 0.3.3 and get the same error.

library(dplyr  , quietly = TRUE)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tsibble, quietly = TRUE)
#> 
#> Attaching package: 'tsibble'
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, union
library(fable  , quietly = TRUE)

tsibble::tourism %>%
  filter(State == 'ACT') %>% 
  aggregate_key(State / Region, Trips = sum(Trips)) %>% 
  model(base = fable::SNAIVE(Trips)) %>%
  reconcile(mint_cov = min_trace(base, method = "mint_cov")) %>% 
  forecast(h = 1)
#> Error in `mutate()`:
#> ℹ In argument: `mint_cov = (function (object, ...) ...`.
#> Caused by error:
#> ! min_trace needs covariance matrix to be positive definite.
#> Backtrace:
#>      ▆
#>   1. ├─... %>% forecast(h = 1)
#>   2. ├─generics::forecast(., h = 1)
#>   3. ├─fabletools:::forecast.mdl_df(., h = 1)
#>   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_mint_mdl(...)
#>  14.   └─rlang::abort(...)

Created on 2023-06-09 with reprex v2.0.2

Session info ``` r sessioninfo::session_info() #> ─ Session info ─────────────────────────────────────────────────────────────── #> setting value #> version R version 4.2.2 (2022-10-31) #> os macOS Ventura 13.4 #> system aarch64, darwin20 #> ui X11 #> language (EN) #> collate en_US.UTF-8 #> ctype en_US.UTF-8 #> tz Australia/Melbourne #> date 2023-06-09 #> pandoc 3.1.1 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown) #> #> ─ Packages ─────────────────────────────────────────────────────────────────── #> ! package * version date (UTC) lib source #> P anytime 0.3.9 2020-08-27 [?] CRAN (R 4.2.0) #> P cli 3.6.0 2023-01-09 [?] CRAN (R 4.2.0) #> P colorspace 2.1-0 2023-01-23 [?] CRAN (R 4.2.0) #> P digest 0.6.31 2022-12-11 [?] CRAN (R 4.2.0) #> P distributional 0.3.1 2022-09-02 [?] CRAN (R 4.2.0) #> P dplyr * 1.1.0 2023-01-29 [?] CRAN (R 4.2.0) #> P ellipsis 0.3.2 2021-04-29 [?] CRAN (R 4.2.0) #> P evaluate 0.20 2023-01-17 [?] CRAN (R 4.2.0) #> P fable * 0.3.3 2023-03-22 [?] CRAN (R 4.2.0) #> P fabletools * 0.3.3.9000 2023-05-28 [?] Github (tidyverts/fabletools@e09af0c) #> P fansi 1.0.4 2023-01-22 [?] CRAN (R 4.2.0) #> P farver 2.1.1 2022-07-06 [?] CRAN (R 4.2.0) #> P fastmap 1.1.1 2023-02-24 [?] CRAN (R 4.2.0) #> P fs 1.6.1 2023-02-06 [?] CRAN (R 4.2.0) #> P generics 0.1.3 2022-07-05 [?] CRAN (R 4.2.0) #> P ggplot2 3.4.2 2023-04-03 [?] CRAN (R 4.2.0) #> P glue 1.6.2 2022-02-24 [?] CRAN (R 4.2.0) #> P gtable 0.3.1 2022-09-01 [?] CRAN (R 4.2.0) #> P htmltools 0.5.4 2022-12-07 [?] CRAN (R 4.2.0) #> P knitr 1.42 2023-01-25 [?] CRAN (R 4.2.0) #> P lattice 0.20-45 2021-09-22 [3] CRAN (R 4.2.2) #> P lifecycle 1.0.3 2022-10-07 [?] CRAN (R 4.2.0) #> P lubridate 1.9.2 2023-02-10 [?] CRAN (R 4.2.0) #> P magrittr 2.0.3 2022-03-30 [?] CRAN (R 4.2.0) #> P Matrix 1.5-1 2022-09-13 [3] CRAN (R 4.2.2) #> P munsell 0.5.0 2018-06-12 [?] CRAN (R 4.2.0) #> P pillar 1.8.1 2022-08-19 [?] CRAN (R 4.2.0) #> P pkgconfig 2.0.3 2019-09-22 [?] CRAN (R 4.2.0) #> P progressr 0.13.0 2023-01-10 [?] CRAN (R 4.2.0) #> P purrr 1.0.1 2023-01-10 [?] CRAN (R 4.2.0) #> P R.cache 0.16.0 2022-07-21 [?] CRAN (R 4.2.0) #> P R.methodsS3 1.8.2 2022-06-13 [?] CRAN (R 4.2.0) #> P R.oo 1.25.0 2022-06-12 [?] CRAN (R 4.2.0) #> P R.utils 2.12.2 2022-11-11 [?] CRAN (R 4.2.0) #> P R6 2.5.1 2021-08-19 [?] CRAN (R 4.2.0) #> P Rcpp 1.0.10 2023-01-22 [?] CRAN (R 4.2.0) #> P reprex 2.0.2 2022-08-17 [?] CRAN (R 4.2.0) #> P rlang 1.1.1 2023-04-28 [?] CRAN (R 4.2.0) #> P rmarkdown 2.20 2023-01-19 [?] CRAN (R 4.2.0) #> P rstudioapi 0.14 2022-08-22 [?] CRAN (R 4.2.0) #> P scales 1.2.1 2022-08-20 [?] CRAN (R 4.2.0) #> sessioninfo 1.2.2 2021-12-06 [3] CRAN (R 4.2.0) #> P styler 1.10.0.9000 2023-06-05 [?] Github (r-lib/styler@d71e2cc) #> P tibble 3.1.8 2022-07-22 [?] CRAN (R 4.2.0) #> P tidyr 1.3.0 2023-01-24 [?] CRAN (R 4.2.0) #> P tidyselect 1.2.0 2022-10-10 [?] CRAN (R 4.2.0) #> P timechange 0.2.0 2023-01-11 [?] CRAN (R 4.2.0) #> P tsibble * 1.1.3 2022-10-09 [?] CRAN (R 4.2.0) #> P utf8 1.2.3 2023-01-31 [?] CRAN (R 4.2.0) #> P vctrs 0.5.2 2023-01-23 [?] CRAN (R 4.2.0) #> P withr 2.5.0 2022-03-03 [?] CRAN (R 4.2.0) #> P xfun 0.37 2023-01-31 [?] CRAN (R 4.2.0) #> P yaml 2.3.7 2023-01-23 [?] CRAN (R 4.2.0) #> #> [1] /Users/mcowgill/Library/CloudStorage/OneDrive-SEEK/seek_projects/seek_forecasting/renv/library/R-4.2/aarch64-apple-darwin20 #> [2] /Users/mcowgill/Library/CloudStorage/OneDrive-SEEK/seek_projects/seek_forecasting/renv/sandbox/R-4.2/aarch64-apple-darwin20/fd29d0b8 #> [3] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library #> #> P ── Loaded and on-disk path mismatch. #> #> ────────────────────────────────────────────────────────────────────────────── ```
MattCowgill commented 1 year ago

I tried running some code from fpp chapter 11.4 - it worked as expected without error. No idea what's going on here...

library(fpp3)
#> ── Attaching packages ────────────────────────────────────────────── fpp3 0.5 ──
#> ✔ tibble      3.1.8     ✔ tsibble     1.1.3
#> ✔ dplyr       1.1.0     ✔ tsibbledata 0.4.1
#> ✔ tidyr       1.3.0     ✔ feasts      0.3.0
#> ✔ lubridate   1.9.2     ✔ fable       0.3.3
#> ✔ ggplot2     3.4.2     ✔ fabletools  0.3.3
#> ── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
#> ✖ lubridate::date()    masks base::date()
#> ✖ dplyr::filter()      masks stats::filter()
#> ✖ tsibble::intersect() masks base::intersect()
#> ✖ tsibble::interval()  masks lubridate::interval()
#> ✖ dplyr::lag()         masks stats::lag()
#> ✖ tsibble::setdiff()   masks base::setdiff()
#> ✖ tsibble::union()     masks base::union()

tourism_full <- tourism |>
  aggregate_key((State/Region) * Purpose, Trips = sum(Trips))

fit <- tourism_full |>
  filter(year(Quarter) <= 2015) |>
  model(base = ETS(Trips)) |>
  reconcile(
    bu = bottom_up(base),
    ols = min_trace(base, method = "ols"),
    mint = min_trace(base, method = "mint_shrink")
  )

fc <- fit |> 
  forecast(h = "2 years")

fc |>
  filter(is_aggregated(Region), is_aggregated(Purpose)) |>
  autoplot(
    tourism_full |> filter(year(Quarter) >= 2011),
    level = NULL
  ) +
  labs(y = "Trips ('000)") +
  facet_wrap(vars(State), scales = "free_y")

Created on 2023-06-09 with reprex v2.0.2