dplyr 中的非标准评估:如何间接调用函数的多个参数?

Non standard evaluation in dplyr: how do you indirect a function's multiple arguments?

我正在尝试编写一个可以将一个或多个参数作为变量传递给 dplyr 函数的函数。我想了解一般如何做。 Programming with dplyr 似乎没有涵盖该问题,您可以在 Google 或小插图(即 ?`!!!`)中找到的一些更具权威性的文档似乎已经过时。下面我提供了一个示例,说明我试图获得什么以及我失败的地方:

df <- as_tibble(mtcars)


df %>% group_by(cyl, gear) %>% summarise(mpg = mean(mpg)) #This is the result I want from a function


testfunc <- function(variables) {
  df %>% group_by({{variables}}) %>% summarise(mpg = mean(mpg))
}

testfunc(cyl)                                             #It works for a single variable

testfunc(cyl, gear)                                       #It fails for multiple variables

testfunc2 <- function(variables) {                        #Second attempt
  variables <- enquos(variables)
  df %>% group_by(!!variables) %>% summarise(mpg = mean(mpg))
}

testfunc2(cyl, gear)                                       #Unused argument error
testfunc2(c(cyl, gear))                                    #Doesn't work
testfunc2(c("cyl", "gear"))                                #Doesn't work

你一般是怎么解决这个问题的?

谢谢!!

您可以为 data.frame 定义一个 arg 并将其他变量的 ... 添加到 分组依据

testfunc <- function(df,...) {
  df %>%
    group_by(...) %>%
    summarise(mpg = mean(mpg))
}
testfunc(mtcars,cyl,gear)  

这在 Hadley Wickham (https://adv-r.hadley.nz/ / https://amzn.to/2WoabjB) 编写的“Advanced R”中有详细介绍,例如第 6、19、20 章:

library(tidyverse)
df <- as_tibble(mtcars)
df %>% group_by(cyl, gear) %>% summarise(mpg = mean(mpg))
#> `summarise()` has grouped output by 'cyl'. You can override using the `.groups` argument.
#> # A tibble: 8 x 3
#> # Groups:   cyl [3]
#>     cyl  gear   mpg
#>   <dbl> <dbl> <dbl>
#> 1     4     3  21.5
#> 2     4     4  26.9
#> 3     4     5  28.2
#> 4     6     3  19.8
#> 5     6     4  19.8
#> 6     6     5  19.7
#> 7     8     3  15.0
#> 8     8     5  15.4

testfunc <- function(variables) {
  df %>% group_by({{variables}}) %>% summarise(mpg = mean(mpg))
}

testfunc(cyl)
#> # A tibble: 3 x 2
#>     cyl   mpg
#>   <dbl> <dbl>
#> 1     4  26.7
#> 2     6  19.7
#> 3     8  15.1
testfunc(cyl, gear)
#> Error in testfunc(cyl, gear): unused argument (gear)

# https://adv-r.hadley.nz/functions.html?q=...#fun-dot-dot-dot
testfunc2 <- function(variables, ...) {                        #Second attempt
  variables <- enquos(variables, ...)
  df %>% group_by(!!!variables) %>% summarise(mpg = mean(mpg))
}

testfunc2(cyl, gear)
#> `summarise()` has grouped output by 'cyl'. You can override using the `.groups` argument.
#> # A tibble: 8 x 3
#> # Groups:   cyl [3]
#>     cyl  gear   mpg
#>   <dbl> <dbl> <dbl>
#> 1     4     3  21.5
#> 2     4     4  26.9
#> 3     4     5  28.2
#> 4     6     3  19.8
#> 5     6     4  19.8
#> 6     6     5  19.7
#> 7     8     3  15.0
#> 8     8     5  15.4

reprex package (v2.0.0)

于 2021-08-23 创建