Awesome! Just extending this idea a bit further... Is it possible to use tidy eval to build expressions in a dplyr pipeline? I can seem to build expressions by first using paste and then parsing them but cannot seem to build the expressions using tidy eval.
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(purrr))
# Get the disinct levels of a few of the variables
vars <- starwars %>%
summarise_all(n_distinct) %>%
tidyr::gather("field", "n_levels") %>%
filter(n_levels < 20) %>%
mutate(levels = purrr::map(field, ~pull(distinct(select(starwars, .)))))
vars
#> # A tibble: 3 x 3
#> field n_levels levels
#> <chr> <int> <list>
#> 1 hair_color 13 <chr [13]>
#> 2 eye_color 15 <chr [15]>
#> 3 gender 5 <chr [5]>
# assign some global variables to use in next pipeline
hair_color <- "black"
eye_color <- "black"
gender <- "female"
# for each row, create an expression and evaluate it.
vars2 <- vars %>%
mutate(my_expr = map2_chr(field, levels, ~paste0(.x, ' %in% c("', paste(.y[1:3], collapse = '","'), '")'))) %>%
mutate(my_expr = map(my_expr, ~rlang::parse_expr(.))) %>%
mutate(result = map_lgl(my_expr, ~eval(., envir = .GlobalEnv)))
# This works!
vars2$my_expr
#> [[1]]
#> hair_color %in% c("blond", "NA", "none")
#>
#> [[2]]
#> eye_color %in% c("blue", "yellow", "red")
#>
#> [[3]]
#> gender %in% c("male", "NA", "female")
vars2$result
#> [1] FALSE FALSE TRUE
# However to get this to work I had to create my expression as a string and then parse it.
# I can't seem to do the same thing using tidy eval.
# I want to skip the step of creating a string and then parsing it.
vars %>%
mutate(my_expr = map2(field, levels, ~rlang::expr(!!.x %in% !!.y[1:3])))
#> Error in quos(...): object '.x' not found
vars %>%
rowwise() %>%
mutate(my_expr = rlang::expr(!!field %in% !!levels[1:3]))
#> Error in quos(...): object 'field' not found
# I seems that rlang::expr does not know where to look up the unquoted variables. (???)
# Created on 2018-04-16 by the reprex package (v0.2.0).