将函数参数传递给dplyr select

kev*_*kuo 5 r dplyr magrittr

要从数据框中选择几列,我可以做

require(dplyr)
require(magrittr)

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

df %>%
  select(col1, col2)
Run Code Online (Sandbox Code Playgroud)

我想写一个类似的函数

f <- function(data, firstCol, secondCol){
   data %>%
    select(substitute(firstCol), substitute(secondCol))
}
Run Code Online (Sandbox Code Playgroud)

但是跑步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)
})()
Run Code Online (Sandbox Code Playgroud)

编辑 - 稍微简单的例子:

假设我想做

mtcars %>%
  select(cyl, hp) %>%
  unique %>%
  group_by(cyl) %>%
  summarise(avgHP = mean(hp))
Run Code Online (Sandbox Code Playgroud)

但具有不同的数据集和不同的变量名称.我可以重用的代码和替换mtcars,cylhp.但我宁愿把它全部包装在一个函数中

had*_*ley 5

在这种情况下它很简单,因为你可以使用......

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

f(df, col1, col2)

#>   col1 col2
#> 1    1    a
#> 2    2    b
#> 3    3    c
Run Code Online (Sandbox Code Playgroud)

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

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


Cha*_* Ye 5

从 rlang 0.4.0 版本开始,curly-curly{{运算符将是一个更好的解决方案。

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
Run Code Online (Sandbox Code Playgroud)