tidymodels/embed

Cannot `update()` a tuneable `step_umap()`

Closed this issue · 2 comments

From this SO question:

library(tidymodels)
library(embed)


## can update this recipe
rec1 <- 
  recipe(Species ~ ., data = iris) %>%
  step_pca(all_numeric_predictors(), num_comp = tune())

update(rec1$steps[[1]], num_comp = 3)
#> $terms
#> <list_of<quosure>>
#> 
#> [[1]]
#> <quosure>
#> expr: ^all_numeric_predictors()
#> env:  0x7f9f3bc3f7b0
#> 
#> 
#> $role
#> [1] "predictor"
#> 
#> $trained
#> [1] FALSE
#> 
#> $num_comp
#> [1] 3
#> 
#> $threshold
#> [1] NA
#> 
#> $options
#> list()
#> 
#> $res
#> NULL
#> 
#> $columns
#> NULL
#> 
#> $prefix
#> [1] "PC"
#> 
#> $keep_original_cols
#> [1] FALSE
#> 
#> $skip
#> [1] FALSE
#> 
#> $id
#> [1] "pca_59xGm"
#> 
#> attr(,"class")
#> [1] "step_pca" "step"


## cannot update this recipe

rec2 <- 
  recipe(Species ~ ., data = iris) %>%
  step_umap(
    all_numeric_predictors(),
    num_comp = tune(),
    outcome = "Species"
  )

update(rec2$steps[[1]], num_comp = 3)
#> Error in structure(list(...), class = c(paste0(.prefix, subclass), "step")): argument is missing, with no default

Created on 2022-03-29 by the reprex package (v2.0.1)

The error crops up in recipes:::reconstruct_step() and more specifically when calling recipes::step(). I haven't tested any other embed steps or updating steps from other recipe extension packages.

This is happening because of the retain argument, which is set to deprecated() which itself calls rlang::missing_args().

embed/R/umap.R

Line 89 in 7a34603

retain = deprecated(),

This means that the step itself has that symbol in the retain element.

library(tidymodels)
library(embed)

rec2 <- 
  recipe(Species ~ ., data = iris) %>%
  step_umap(
    all_numeric_predictors(),
    num_comp = tune(),
    outcome = "Species"
  )

str(rec2$steps[[1]])
#> List of 17
#>  $ terms             :List of 1
#>   ..$ : language ~all_numeric_predictors()
#>   .. ..- attr(*, ".Environment")=<environment: 0x12623c7f0> 
#>   ..- attr(*, "class")= chr [1:2] "quosures" "list"
#>  $ role              : chr "predictor"
#>  $ trained           : logi FALSE
#>  $ outcome           : chr "Species"
#>  $ neighbors         : num 15
#>  $ num_comp          : language tune()
#>  $ min_dist          : num 0.01
#>  $ learn_rate        : num 1
#>  $ epochs            : NULL
#>  $ options           :List of 2
#>   ..$ verbose  : logi FALSE
#>   ..$ n_threads: num 1
#>  $ seed              : int [1:2] 84398 15440
#>  $ prefix            : chr "UMAP"
#>  $ keep_original_cols: logi FALSE
#>  $ retain            : symbol 
#>  $ object            : NULL
#>  $ skip              : logi FALSE
#>  $ id                : chr "umap_cU0wI"
#>  - attr(*, "class")= chr [1:2] "step_umap" "step"

This means that when we try to reconstruct the step it creates a call that has retain = , which throws an error when evaluated.

subclass <- setdiff(class(rec2$steps[[1]]), "step")
args <- unclass(rec2$steps[[1]])

call_step <- rlang::call2(
  .fn = "step",
  subclass = subclass,
  !!!args,
  .prefix = "",
  .ns = "recipes"
)

call_step
#> recipes::step(subclass = "step_umap", terms = list(~all_numeric_predictors()), 
#>     role = "predictor", trained = FALSE, outcome = "Species", 
#>     neighbors = 15, num_comp = tune(), min_dist = 0.01, learn_rate = 1, 
#>     epochs = NULL, options = list(verbose = FALSE, n_threads = 1), 
#>     seed = c(84398L, 15440L), prefix = "UMAP", keep_original_cols = FALSE, 
#>     retain = , object = NULL, skip = FALSE, id = "umap_cU0wI", 
#>     .prefix = "")

rlang::eval_tidy(call_step)
#> Error in structure(list(...), class = c(paste0(.prefix, subclass), "step")): argument is missing, with no default

Created on 2022-03-30 by the reprex package (v2.0.1)

This issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with a reprex: https://reprex.tidyverse.org) and link to this issue.