I am building a function that requires the user to occasionally pass multiple variables into an argument. The function already uses ... for something else.
I was trying to do this using {{ }} but passing multiple variables to {{ }} only works sometimes.
Here are two functions that both use {{ }}. Both functions work when the user passes a single variable to {{ }}, but the second function fails when passed multiple variables.
Can you help me:
Understand why the first function succeeds, and the second fails when given multiple variables?
fix function 2 so I can pass multiple arguments without using ...
library(tidyverse)
# Function 1
select_and_summarise <- function(.data, selected, ...){
.data %>%
select({{selected}}) %>%
summarise_all(list(...))
}
# Function 2
group_and_summarise <- function(.data, group, ...){
.data %>%
group_by({{group}}) %>%
summarise_all(list(...))
}
# Passing single variables work
mtcars %>%
select_and_summarise(selected = cyl, mean = mean)
mtcars %>%
group_and_summarise(group = cyl, mean = mean)
# Passing more than one variable only works for select_and_summarise
mtcars %>%
select_and_summarise(selected = c(cyl, mpg, hp), mean = mean)
mtcars %>%
group_and_summarise(group = c(cyl, mpg, hp), mean = mean)
EDIT
Following Hadleys advice I made this function that works for both the examples I've given:
The first function succeeds because select() is designed this way — select(df, c(x, y, z)) is a valid select call. The second function fails because group_by(df, c(x, y, z)) is not a valid call to group_by(). One way to resolve your problem would be to use group_by_at() which uses selection semantics (like select()), rather than action semantics (like group_by()/mutate()). This would mean that the user can't create new grouping variables, but I think that's a sacrifice you have to make.
@valeri unfortunately your approach will fail if the user groups by a function of existing variables (as a call object has length equal to the number of arguments plus one).