使用tidyeval

时间:2017-07-26 16:37:40

标签: r dplyr rlang tidyeval

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

选择很简单我可以通过像这样的字符串选择字段

(function(field) { 
  mpg %>% dplyr::select(field) 
})("cyl")

通过多个字符串的多个字段,如

(function(...) { 
  mpg %>% dplyr::select(!!!quos(...)) 
})("cyl", "hwy")

和多个字段通过长度为>的一个字符向量1喜欢这个

(function(fields) {  
  mpg %>% dplyr::select(fields)  
})(c("cyl", "hwy"))

使用group_by我无法真正找到一种方法来为多个字符串执行此操作,因为如果我设法获得输出,它最终会按我提供的字符串进行分组。

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

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

这已经很难看了。

有谁知道我要写什么,所以我可以运行

(function(field) {...})("cyl", "hwy")

(function(field) {...})(c("cyl", "hwy"))

分别?我尝试了!!!!!UQenquoquosunlist等各种组合...并保存它们在中间变量中,因为这有时似乎有所不同,但却无法使其发挥作用。

1 个答案:

答案 0 :(得分:3)

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

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

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

myselect("cyl", "disp")
mygroup("cyl", "disp")

要调试unquoting,请使用expr()换行并检查表达式是否正确:

syms <- syms(list("cyl", "disp"))
expr(group_by(mtcars, !!! syms))
#> group_by(mtcars, cyl, disp)    # yup, looks right!

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

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

group_by_at(mtcars, c("cyl", "disp"))