使用 tidyeval 的具有非标量字符向量的 group_by

Rob*_*ach 0 r dplyr tidyeval rlang

使用R 3.2.2dplyr 0.7.2我试图弄清楚如何有效地使用group_by作为字符向量提供的字段。

选择很容易我可以通过这样的字符串选择一个字段

(function(field) { 
  mpg %>% dplyr::select(field) 
})("cyl")
Run Code Online (Sandbox Code Playgroud)

通过像这样的多个字符串的多个字段

(function(...) { 
  mpg %>% dplyr::select(!!!quos(...)) 
})("cyl", "hwy")
Run Code Online (Sandbox Code Playgroud)

和多个字段,通过一个长度 > 1 的字符向量,像这样

(function(fields) {  
  mpg %>% dplyr::select(fields)  
})(c("cyl", "hwy"))
Run Code Online (Sandbox Code Playgroud)

随着group_by我真的不能找到一种方法,因为如果我设法得到一个输出它结束了由字符串我供应分组为多个字符串做到这一点。

我设法按这样的一个字符串分组

(function(field) {  
  mpg %>% group_by(!!field := .data[[field]]) %>% tally() 
})("cyl")
Run Code Online (Sandbox Code Playgroud)

这已经很丑了。

有谁知道我必须写什么,以便我可以运行

(function(field) {...})("cyl", "hwy")
Run Code Online (Sandbox Code Playgroud)

(function(field) {...})(c("cyl", "hwy"))
Run Code Online (Sandbox Code Playgroud)

分别?我试过各种组合!!!!!UQenquoquosunlist,等...,并将其保存在中间变量,因为,有时似乎有所作为,但它不能去工作。

Lio*_*nry 5

select()在 dplyr 中非常特别。它不接受,但接受位置。所以这是唯一接受字符串的主要动词。(从技术上讲,当你提供一个像cylselect这样的裸名称时,它实际上被评估为它自己的名字,而不是数据框内的向量。)

如果您希望您的函数采用简单的字符串,而不是纯粹的表达式或符号,则不需要 quosures。只需从字符串创建符号并取消引用它们:

myselect <- function(...) {
  syms <- syms(list(...))
  select(mtcars, !!! syms)
}
mygroup <- function(...) {
  syms <- syms(list(...))
  group_by(mtcars, !!! syms)
}

myselect("cyl", "disp")
mygroup("cyl", "disp")
Run Code Online (Sandbox Code Playgroud)

要调试取消引用,请使用expr()并检查表达式是否正确:

syms <- syms(list("cyl", "disp"))
expr(group_by(mtcars, !!! syms))
#> group_by(mtcars, cyl, disp)    # yup, looks right!
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅此演讲(我们将更新编程小插图以使概念更清晰):https : //schd.ws/hosted_files/user2017/43/tidyeval-user.pdf

最后,请注意,许多动词都有一个_at后缀变体,可以毫不费力地接受字符串和字符向量:

group_by_at(mtcars, c("cyl", "disp"))
Run Code Online (Sandbox Code Playgroud)