如何使用非标准评估NSE评估data.table上的参数? [英] How to use non-standard evaluation NSE to evaluate arguments on data.table?
问题描述
说我有以下内容
library(data.table)
cars1 = setDT(copy(cars))
cars2 = setDT(copy(cars))
car_list = list(cars1, cars2)
class(car_list) <- "dd"
`[.dd` <- function(x,...) {
code = rlang::enquos(...)
cars1 = x[[1]]
rlang::eval_tidy(quo(cars1[!!!code]))
}
car_list[,.N, by = speed]
所以我希望通过定义[.dd
函数在cars1
和cars2
上执行任意操作,以便使用[
数据通过cars1
和cars2
执行我放入...
的任何内容.table语法,例如
so I wished to perform arbitrary operations on cars1
and cars2
by defining the [.dd
function so that whatever I put into ...
get executed by cars1
and cars2
using the [
data.table syntax e.g.
car_list[,.N, by = speed]
应该执行以下操作
cars1[,.N, by = speed]
cars2[,.N, by = speed]
我也想要
car_list[,speed*2]
要做
cars1[,speed*2]
cars2[,speed*2]
基本上,[.dd
中的...
必须接受任意代码.
Basically, ...
in [.dd
has to accept arbitrary code.
我需要捕获...
,所以我尝试执行code = rlang::enquos(...)
,然后rlang::eval_tidy(quo(cars1[!!!code]))
无法正常工作并给出错误
somehow I need to capture the ...
so I tried to do code = rlang::enquos(...)
and then rlang::eval_tidy(quo(cars1[!!!code]))
doesn't work and gives error
[.data.table
中的错误(cars1,〜,〜.N,by =〜speed): 参数"i"丢失,没有默认值
Error in
[.data.table
(cars1, ~, ~.N, by = ~speed) : argument "i" is missing, with no default
推荐答案
第一个基本R选项是substitute(...())
,后跟do.call
:
First base R option is substitute(...())
followed by do.call
:
library(data.table)
cars1 = setDT(copy(cars))
cars2 = setDT(copy(cars))
cars2[, speed := sort(speed, decreasing = TRUE)]
car_list = list(cars1, cars2)
class(car_list) <- "dd"
`[.dd` <- function(x,...) {
a <- substitute(...()) #this is an alist
expr <- quote(x[[i]])
expr <- c(expr, a)
res <- list()
for (i in seq_along(x)) {
res[[i]] <- do.call(data.table:::`[.data.table`, expr)
}
res
}
all.equal(
car_list[,.N, by = speed],
list(cars1[,.N, by = speed], cars2[,.N, by = speed])
)
#[1] TRUE
all.equal(
car_list[, speed*2],
list(cars1[, speed*2], cars2[, speed*2])
)
#[1] TRUE
第二个基本R选项是match.call
,修改调用,然后求值(您可以在lm
中找到此方法):
Second base R option is match.call
, modify the call and then evaluate (you find this approach in lm
):
`[.dd` <- function(x,...) {
thecall <- match.call()
thecall[[1]] <- quote(`[`)
thecall[[2]] <- quote(x[[i]])
res <- list()
for (i in seq_along(x)) {
res[[i]] <- eval(thecall)
}
res
}
all.equal(
car_list[,.N, by = speed],
list(cars1[,.N, by = speed], cars2[,.N, by = speed])
)
#[1] TRUE
all.equal(
car_list[, speed*2],
list(cars1[, speed*2], cars2[, speed*2])
)
#[1] TRUE
如果您使用:=
,我还没有测试过这些方法是否可以复制深层副本.
I haven't tested if these approaches will make a deep copy if you use :=
.
这篇关于如何使用非标准评估NSE评估data.table上的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!