为了使自定义函数灵活地接收我当前依赖的每个形式参数的一个或多个调用参数"…":
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个或多个需要多个调用参数的形式参数的自定义函数中使用。
有没有一种方法可以编写上面的函数来使用一个形式参数(例如,"group"(而不是"…",它可以接收单个矢量名称或矢量名称的矢量作为其参数?类似于:
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)
我希望在函数体中使用enkos((。
我们可以将...
放置在的末尾
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