How can I iterate over functions that use tidy evaluation (via rlang's curly-curly)?
Here's a basic example, where I attempt to iterate over column names using purrr::map():
library("dplyr")
library("purrr")
myfunc <- function(by) {
mtcars %>% count({{ by }})
}
# passing unquoted arguments doesn't work
c(cyl, vs, am, gear) %>% map(~ myfunc(by = .x))
#> Error in eval(expr, envir, enclos): object 'cyl' not found
# passing quoted arguments also doesn't work
c("cyl", "vs", "am", "gear") %>% map(~ myfunc(by = .x))
#> Error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `count()`:
#> ! Must group by variables found in `.data`.
#> ✖ Column `.x` is not found.
Created on 2024-03-18 with reprex v2.1.0
How to get around this problem?
When you try to create a vector of unquoted symbols
c(cyl, vs, am, gear), R will try to evaluate this before the next step in the pipeline. None ofcyl,vs,amorgearexist in the global environment, so this will fail.If you want to do things this way, you can explicitly tell R that these arguments shouldn't be evaluated until later, which can be done using
rlang::quos():Created on 2024-03-18 with reprex v2.1.0
Note that you'll also need to use
!!for this to work - otherwise R will look for a column called.x.A more idiomatic approach would be to use a character vector and to subset the
.datapronoun like so:You could also use
across()combined withall_of():As you can see, there are lots of approaches you can take - this is called non-standard evaluation (NSE), and it's a broad topic. To learn more I'd recommend reading
vignette("programming", package = "dplyr")and the set of articles on metaprogramming from the {rlang} documentation.