问题
rlang
包中的{{}}
运算符使将列名作为函数参数(也称为Quasiquote)传递变得非常容易。我知道rlang
是用来与tidyverse
配合使用的,但有没有办法在data.table
中使用{{}}
?
{{}}与dplyr的预期用途
test_dplyr <- function(dt, col1, col2){
temp <- dt %>%
group_by( {{col2}} ) %>%
summarise(test = mean( {{col1}} ))
return(temp)
}
test_dplyr(dt=iris, col1=Sepal.Length, col2=Species)
> # A tibble: 3 x 2
> Species test
> <fct> <dbl>
> 1 setosa 5.01
> 2 versicolor 5.94
> 3 virginica 6.59
尝试将{{}}与data.table一起使用失败
这是理想情况下我想做的,但它返回一个ERROR。
test_dt2 <- function(dt, col1, col2){
data.table::setDT(dt)
temp <- dt[, .( test = mean({{col1}})), by = {{col2}} ] )
return(temp)
}
# error
test_dt2(dt=iris, col1= Sepal.Length, col2= Species)
# and error
test_dt2(dt=iris, col1= 'Sepal.Length', col2= 'Species')
rlang与data.table的替代使用
这里有一种将rlang
与data.table
结合使用的替代方法。这里有两个不相容性,一个是对每个列名变量rlang::ensym()
,另一个是必须在rlang::injec()
内部调用data.table操作。
test_dt <- function(dt, col1, col2){
# eval colnames
col1 <- rlang::ensym(col1)
col2 <- rlang::ensym(col2)
data.table::setDT(dt)
temp <- rlang::inject( dt[, .( test = mean(!!col1)), by = !!col2] )
return(temp)
}
test_dt(dt=iris, col1='Sepal.Length', col2='Species')
> Species test
> 1: setosa 5.006
> 2: versicolor 5.936
> 3: virginica 6.588
我认为您不想将rlang与data.table一起使用。data.table本身已经有了更方便的功能。还建议不要在这里使用setDT,因为这会导致更改dt的副作用。
library(data.table)
test_dt <- function(dt, col1, col2) {
as.data.table(dt)[, .( test = mean(.SD[[col1]])), by = c(col2)]
}
test_dt(dt = iris, col1 = 'Sepal.Length', col2 = 'Species')
## Species test
## 1: setosa 5.006
## 2: versicolor 5.936
## 3: virginica 6.588
这也起作用:
test_dt <- function(dt, col1, col2) {
as.data.table(dt)[, .( test = mean(get(col1))), by = c(col2)]
}
test_dt(dt=iris, col1='Sepal.Length', col2='Species')