tidyverts / tidyverts/fabletools

parameterized model formulas stop working when future `plan` is declared

Open
#405 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

parellel
Dominant language
R
Stars
98
Forks
37
PR merge metrics
No merged PRs in 30d

Description

See reprex below. In my real codebase I'm using furrr's future_map for other purposes (reading a series of files off disk).

library(fable)
#> Loading required package: fabletools
library(tsibble)
#> 
#> Attaching package: 'tsibble'
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, union
library(feasts)
library(glue)
library(future)

# Define some random data
set.seed(7)
data <- tsibble(idx=1:1000, value=rnorm(1000), index=idx) 

# Make a STL decomposition
model(data, stl = STL(value ~ trend() + season(10))) %>% components()
#> # A dable: 1,000 x 7 [1]
#> # Key:     .model [1]
#> # :        value = trend + season_10 + remainder
#>    .model   idx  value   trend season_10 remainder season_adjust
#>    <chr>  <int>  <dbl>   <dbl>     <dbl>     <dbl>         <dbl>
#>  1 stl        1  2.29  -0.477     0.419      2.35         1.87  
#>  2 stl        2 -1.20  -0.349     0.141     -0.988       -1.34  
#>  3 stl        3 -0.694 -0.222     0.279     -0.751       -0.973 
#>  4 stl        4 -0.412 -0.0899   -0.443      0.121        0.0311
#>  5 stl        5 -0.971  0.0418    0.0143    -1.03        -0.985 
#>  6 stl        6 -0.947  0.170    -0.350     -0.767       -0.597 
#>  7 stl        7  0.748  0.298     0.0246     0.426        0.724 
#>  8 stl        8 -0.117  0.431    -0.214     -0.334        0.0972
#>  9 stl        9  0.153  0.564    -0.300     -0.112        0.453 
#> 10 stl       10  2.19   0.706     0.459      1.02         1.73  
#> # ℹ 990 more rows

# We can use a variable in the formula
seasonal_period <- 10
model(data, stl = STL(value ~ trend() + season(seasonal_period))) %>% components()
#> # A dable: 1,000 x 7 [1]
#> # Key:     .model [1]
#> # :        value = trend + season_10 + remainder
#>    .model   idx  value   trend season_10 remainder season_adjust
#>    <chr>  <int>  <dbl>   <dbl>     <dbl>     <dbl>         <dbl>
#>  1 stl        1  2.29  -0.477     0.419      2.35         1.87  
#>  2 stl        2 -1.20  -0.349     0.141     -0.988       -1.34  
#>  3 stl        3 -0.694 -0.222     0.279     -0.751       -0.973 
#>  4 stl        4 -0.412 -0.0899   -0.443      0.121        0.0311
#>  5 stl        5 -0.971  0.0418    0.0143    -1.03        -0.985 
#>  6 stl        6 -0.947  0.170    -0.350     -0.767       -0.597 
#>  7 stl        7  0.748  0.298     0.0246     0.426        0.724 
#>  8 stl        8 -0.117  0.431    -0.214     -0.334        0.0972
#>  9 stl        9  0.153  0.564    -0.300     -0.112        0.453 
#> 10 stl       10  2.19   0.706     0.459      1.02         1.73  
#> # ℹ 990 more rows


# Or we can make a formula ourselves
stl_formula <- as.formula(glue("value ~ trend() + season({seasonal_period})"))
stl_formula
#> value ~ trend() + season(10)

# ... and hand it to STL
model(data, stl = STL(stl_formula)) %>% components()
#> # A dable: 1,000 x 7 [1]
#> # Key:     .model [1]
#> # :        value = trend + season_10 + remainder
#>    .model   idx  value   trend season_10 remainder season_adjust
#>    <chr>  <int>  <dbl>   <dbl>     <dbl>     <dbl>         <dbl>
#>  1 stl        1  2.29  -0.477     0.419      2.35         1.87  
#>  2 stl        2 -1.20  -0.349     0.141     -0.988       -1.34  
#>  3 stl        3 -0.694 -0.222     0.279     -0.751       -0.973 
#>  4 stl        4 -0.412 -0.0899   -0.443      0.121        0.0311
#>  5 stl        5 -0.971  0.0418    0.0143    -1.03        -0.985 
#>  6 stl        6 -0.947  0.170    -0.350     -0.767       -0.597 
#>  7 stl        7  0.748  0.298     0.0246     0.426        0.724 
#>  8 stl        8 -0.117  0.431    -0.214     -0.334        0.0972
#>  9 stl        9  0.153  0.564    -0.300     -0.112        0.453 
#> 10 stl       10  2.19   0.706     0.459      1.02         1.73  
#> # ℹ 990 more rows

# The same thing works with ARIMA
fixed_p <- 1
model(data, arima = ARIMA(value ~ pdq(p=fixed_p))) %>% tidy()
#> # A tibble: 1 × 6
#>   .model term  estimate std.error statistic p.value
#>   <chr>  <chr>    <dbl>     <dbl>     <dbl>   <dbl>
#> 1 arima  ar1     0.0194    0.0317     0.612   0.541

arima_formula <- as.formula(glue("value ~ pdq(p={fixed_p})"))
model(data, arima = ARIMA(arima_formula)) %>% tidy()
#> # A tibble: 1 × 6
#>   .model term  estimate std.error statistic p.value
#>   <chr>  <chr>    <dbl>     <dbl>     <dbl>   <dbl>
#> 1 arima  ar1     0.0194    0.0317     0.612   0.541

# But the moment we declare a plan ...
plan(multisession, workers=8)

# ... "normal" formula with no parameters still works, ...
model(data, stl = STL(value ~ trend() + season(10))) %>% components()
#> # A dable: 1,000 x 7 [1]
#> # Key:     .model [1]
#> # :        value = trend + season_10 + remainder
#>    .model   idx  value   trend season_10 remainder season_adjust
#>    <chr>  <int>  <dbl>   <dbl>     <dbl>     <dbl>         <dbl>
#>  1 stl        1  2.29  -0.477     0.419      2.35         1.87  
#>  2 stl        2 -1.20  -0.349     0.141     -0.988       -1.34  
#>  3 stl        3 -0.694 -0.222     0.279     -0.751       -0.973 
#>  4 stl        4 -0.412 -0.0899   -0.443      0.121        0.0311
#>  5 stl        5 -0.971  0.0418    0.0143    -1.03        -0.985 
#>  6 stl        6 -0.947  0.170    -0.350     -0.767       -0.597 
#>  7 stl        7  0.748  0.298     0.0246     0.426        0.724 
#>  8 stl        8 -0.117  0.431    -0.214     -0.334        0.0972
#>  9 stl        9  0.153  0.564    -0.300     -0.112        0.453 
#> 10 stl       10  2.19   0.706     0.459      1.02         1.73  
#> # ℹ 990 more rows

# ... but the above strategies for parameterizing the formula stop working
model(data, stl = STL(stl_formula)) %>% components()
#> Error: object 'stl_formula' not found
model(data, stl = STL(value ~ trend() + season(seasonal_period))) %>% components()
#> Warning: 1 error encountered for stl
#> [1] object 'seasonal_period' not found
#> Error in `transmute()`:
#> ℹ In argument: `cmp = map(.fit, components)`.
#> Caused by error in `UseMethod()`:
#> ! no applicable method for 'components' applied to an object of class "null_mdl"
#> Backtrace:
#>      ▆
#>   1. ├─... %>% components()
#>   2. ├─generics::components(.)
#>   3. ├─fabletools:::components.mdl_df(.)
#>   4. │ ├─dplyr::transmute(...)
#>   5. │ └─dplyr:::transmute.data.frame(...)
#>   6. │   └─dplyr:::mutate_cols(.data, dots, by)
#>   7. │     ├─base::withCallingHandlers(...)
#>   8. │     └─dplyr:::mutate_col(dots[[i]], data, mask, new_columns)
#>   9. │       └─mask$eval_all_mutate(quo)
#>  10. │         └─dplyr (local) eval()
#>  11. ├─fabletools:::map(.fit, components)
#>  12. │ └─base::lapply(.x, .f, ...)
#>  13. │   ├─generics (local) FUN(X[[i]], ...)
#>  14. │   └─fabletools:::components.mdl_ts(X[[i]], ...)
#>  15. │     └─generics::components(object$fit, ...)
#>  16. └─base::.handleSimpleError(...)
#>  17.   └─dplyr (local) h(simpleError(msg, call))
#>  18.     └─rlang::abort(message, class = error_class, parent = parent, call = error_call)
model(data, arima = ARIMA(arima_formula)) %>% tidy()
#> Error: object 'arima_formula' not found

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure using model() with STL() and ARIMA() after plan(multisession, workers=8), comparing literal formulas with formulas containing parameters. Trace how these model entry points capture formula environments under the future plan; done means both parameterized forms work without missing-object errors and retain their existing results.

Written by the indexing model from the issue text.

Assessment

Tech stack
r
Domain
data
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.