将函数参数传递给dplyr select

7
为了从数据框中选择一些列,我可以这样做:
require(dplyr)
require(magrittr)

df <- data.frame(col1=c(1, 2, 3), col2=letters[1:3], col3=LETTERS[4:6])

df %>%
  select(col1, col2)

我想编写一个类似于以下函数的功能:

f <- function(data, firstCol, secondCol){
   data %>%
    select(substitute(firstCol), substitute(secondCol))
}

但是运行 f(df, col1, col2) 时会出现错误。
Error in select_vars(names(.data), ..., env = parent.frame()) : 
  (list) object cannot be coerced to type 'double'
Called from: (function () 
{
    .rs.breakOnError(TRUE)
})()

编辑——稍微复杂的例子:

假设我想要执行下面的操作:

mtcars %>%
  select(cyl, hp) %>%
  unique %>%
  group_by(cyl) %>%
  summarise(avgHP = mean(hp))

但使用不同的数据集和变量名时,我可以重用代码并替换mtcarscylhp。但我宁愿把所有内容都包装在一个函数中。


2
也许这篇帖子(由@hadley回答)是相关的? - Henrik
只是好奇,有人最终解决了稍微不那么琐碎的例子吗? - tim
1
@tim 请查看http://cran.r-project.org/web/packages/dplyr/vignettes/nse.html,自去年以来有很多变化。 - kevinykuo
@organicagave 感谢您指引我正确的方向。 - tim
2个回答

6

在这种情况下,非常简单,因为您可以直接使用...

f <- function(data, ...) {
  data %>% select(...)
}

f(df, col1, col2)

#>   col1 col2
#> 1    1    a
#> 2    2    b
#> 3    3    c

在更一般的情况下,您有两个选项:

  1. 等到 https://github.com/hadley/dplyr/issues/352 关闭
  2. 使用 substitute() 构建完整表达式,然后使用 eval()

事实上,在这种情况下,你甚至可以使用:f <- select - G. Grothendieck

5

自从rlang 0.4.0版本以来,双大括号{{运算符将是更好的解决方案。

f <- function(data, firstCol, secondCol){
   data %>%
    select({{ firstCol }}, {{ secondCol }})
}

df <- data.frame(col1=c(1, 2, 3), col2=letters[1:3], col3=LETTERS[4:6])

df %>% f(col1, col2)

#   col1 col2
# 1    1    a
# 2    2    b
# 3    3    c

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接