Передайте несколько вызывающих аргументов формальному аргументу в пользовательской функции dplyr без использования "..."
Чтобы сделать настраиваемую функцию гибкой для получения одного или нескольких вызывающих аргументов на формальный аргумент, я в настоящее время полагаюсь на "...":
library(dplyr)
foo <- function(data, ..., dv){
groups <- enquos(...)
dv <- enquo(dv)
data %>%
group_by(!!!groups) %>%
summarise(group_mean = mean(!!dv))
}
mtcars %>% foo(am, dv = mpg)
mtcars %>% foo(vs, am, dv = mpg)
Но "..." скрывает логику функции, и ее нельзя использовать в пользовательской функции с 2 или более формальными аргументами, требующими нескольких вызывающих аргументов.
Есть ли способ написать вышеупомянутую функцию для использования формального аргумента (например, "groups") вместо "...", который может получить одно имя вектора или вектор имен векторов в качестве аргумента (ов)? Что-то вроде:
foo <- function(data, groups, dv){
groups <- enquos(groups)
dv <- enquo(dv)
data %>%
group_by(!!!groups) %>%
summarise(group_mean = mean(!!dv))
}
# Failing code
mtcars %>% foo(groups = c(vs, am), dv = mpg)
Обратите внимание, что этот код будет работать, но необходимо, чтобы пользователь не забывал использовать quos() в теле функции:
foo <- function(data, groups, dv){
dv <- enquo(dv)
data %>%
group_by(!!!groups) %>%
summarise(group_mean = mean(!!dv))
}
mtcars %>% foo(groups = quos(vs, am), dv = mpg)
Я хотел бы положиться на enquos() в теле функции вместо этого.
1 ответ
Мы могли бы разместить ...
в конце
foo <- function(data, dv, ...){
groups <- enquos(...)
dv <- enquo(dv)
data %>%
group_by(!!!groups) %>%
summarise(group_mean = mean(!!dv))
}
Если мы хотим передать vector
"группа", то один из вариантов group_by_at
foo <- function(data, groups, dv){
dv <- enquo(dv)
data %>%
group_by_at(vars(groups)) %>%
summarise(group_mean = mean(!!dv))
}
mtcars %>%
foo(groups = c("vs", "am"), dv = mpg)
# A tibble: 4 x 3
# Groups: vs [?]
# vs am group_mean
# <dbl> <dbl> <dbl>
#1 0 0 15.0
#2 0 1 19.8
#3 1 0 20.7
#4 1 1 28.4
Один вариант, если мы хотим передать выражение без кавычек с c
будет преобразовать его в выражение, а затем оценить его
foo <- function(data, groups, dv){
groups <- as.list(rlang::enexpr(groups))[-1]
dv <- enquo(dv)
data %>%
group_by(!!! groups) %>%
summarise(group_mean = mean(!!dv))
}
mtcars %>%
foo(groups = c(vs, am), dv = mpg)
# A tibble: 4 x 3
# Groups: vs [?]
# vs am group_mean
# <dbl> <dbl> <dbl>
#1 0 0 15.0
#2 0 1 19.8
#3 1 0 20.7
#4 1 1 28.4
Или, как @Joe упомянул в комментариях, enquo
также должен работать с group_by_at
foo <- function(data, groups, dv){
dv <- enquo(dv)
groups <- enquos(groups)
data %>%
group_by_at(vars(!!!groups)) %>%
summarise(group_mean = mean(!!dv))
}
mtcars %>%
foo(groups = c(vs, am), dv = mpg)
# A tibble: 4 x 3
# Groups: vs [?]
# vs am group_mean
# <dbl> <dbl> <dbl>
#1 0 0 15.0
#2 0 1 19.8
#3 1 0 20.7
#4 1 1 28.4