Let's pick this apart. data_grid()
is basically a few calls to tidyr::crossing()
.
data_grid <- function (data, ..., .model = NULL) {
expanded <- tidyr::expand(data, ...)
if (is.null(.model))
return(expanded)
needed <- setdiff(predictor_vars(.model), names(expanded))
typical <- tidyr::crossing_(lapply(data[needed], typical))
tidyr::crossing(expanded, typical)
}
crossing()
takes named vectors and generates all crossed combinations of them.
library(tidyverse)
crossing(x = 1:3, y = 1:2)
#> # A tibble: 6 x 2
#> x y
#> <int> <int>
#> 1 1 1
#> 2 1 2
#> 3 2 1
#> 4 2 2
#> 5 3 1
#> 6 3 2
The error arises in the line with crossing_()
. Back in the day, say 2015-2016 , tidyverse dataframe functions, like select()
, filter()
or here crossing()
, had variants that were geared for programming in packages, and they all ended in _()
. These are being phased out as part of the adoption of "tidy evaluation" framework. So... it looks like this error is a bug in the migration from lazyeval to tidyeval. We can fix this by converting the line to use the new framework.
tidyr::crossing()
works on a bunch of named vectors. lapply(data[needed], typical)
applies typical()
to each column in data[needed]
storing the results in a list. Here's an example on the iris data-set.
lapply(iris, typical)
#> $Sepal.Length
#> [1] 5.8
#>
#> $Sepal.Width
#> [1] 3
#>
#> $Petal.Length
#> [1] 4.35
#>
#> $Petal.Width
#> [1] 1.3
#>
#> $Species
#> [1] "setosa" "versicolor" "virginica"
We need to convert this list into a bunch of named vectors for crossing()
. In the new tidyeval framework, we can splice a list using !!!
. We are kinda popping open a list bubble and spilling each of its vectors into crossing(...)
.
crossing(!!! lapply(iris, typical))
#> # A tibble: 3 x 5
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1 5.8 3 4.35 1.3 setosa
#> 2 5.8 3 4.35 1.3 versicolor
#> 3 5.8 3 4.35 1.3 virginica
Thus to fix the function, we fix that one line.
data_grid2 <- function (data, ..., .model = NULL) {
expanded <- tidyr::expand(data, ...)
if (is.null(.model))
return(expanded)
needed <- setdiff(modelr:::predictor_vars(.model), names(expanded))
typical <- tidyr::crossing(!!! lapply(data[needed], typical))
tidyr::crossing(expanded, typical)
}
smaller %>%
data_grid2(cut, .model = mod_diamond2) %>%
add_predictions(mod_diamond2)
#> # A tibble: 5 x 5
#> cut carat color clarity pred
#> <ord> <dbl> <chr> <chr> <dbl>
#> 1 Fair 0.7 G SI1 1923.252
#> 2 Good 0.7 G SI1 2563.082
#> 3 Very Good 0.7 G SI1 2756.650
#> 4 Premium 0.7 G SI1 2776.789
#> 5 Ideal 0.7 G SI1 2909.394
Alternatively, if we don't want to use !!!
, we might change how the crossing()
function works instead, using a lift_
adverb from purrr. Specifically, lift_dl()
lifts a function from working on dots d
to working on a list l
instead.
purrr::lift_dl(crossing)(lapply(iris, typical))
#> # A tibble: 3 x 5
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1 5.8 3 4.35 1.3 setosa
#> 2 5.8 3 4.35 1.3 versicolor
#> 3 5.8 3 4.35 1.3 virginica