如何在不破坏 data.table 的自定义评估的情况下调整 `[.data.table` 中的 j?
How to adjust j in `[.data.table` without breaking data.table's custom evaluation?
我正在尝试将 data.table
扩展到 speed up/standardize analyses of complex survey designs。为此,我尝试在 [.data.table
之上添加一个光层,在其中拦截 j
中的调用,并在某些情况下替换操作(例如 mean
到 median
) 当需要特殊测量类型命令时(或者当不需要特殊命令时使用普通函数以利用 data.table
的 geforce 类型优化)。
根据我对 s3 dispatch 的部分理解,NextMethod
应该是这里合适的函数,但它似乎将 j
作为符号 j
传递(例如 a[, j]
而不是与 data.table 的 NSE 奇怪地交互的 a[, median(v1)]
。我已经尝试过带有 do.call 的版本,但无法通过一些无限递归废话(do.call('[', ...)
将无休止地发送 [.dtsurvey
)
是否有一种简洁的方法来调整参数并将其传递给 data.table
?在下面的玩具示例中,我希望调用 return 列 v1
的 median
,即使初始操作是 mean
.
library('data.table')
a = data.table(v1 = 1:10)
b = copy(a)
"[.dtsurvey" <- function(x, i, j, by, ...){
j = substitute(j)
print(j)
if(j[[1]] == 'mean') j[[1]] = quote(median)
print(j)
NextMethod(`[`, x)
}
class(a) <- c('dtsurvey', class(a))
a[, mean(v1)]
#> mean(v1)
#> median(v1)
#> Error in `[.data.table`(a, , mean(v1)): j (the 2nd argument inside [...]) is a single symbol but column name 'j' is not found. Perhaps you intended DT[, ..j]. This difference to data.frame is deliberate and explained in FAQ 1.1.
由 reprex package (v0.3.0)
于 2020-10-08 创建
我认为您无法在此处利用 NextMethod,据我所知,它会考虑传递的参数。这是一种方法:
library(data.table)
a = data.table(v1 = c(1,2,9))
b = copy(a)
"[.dtsurvey" <- function(x, i, j, by, ...){
mc <- match.call()
j <- substitute(j)
j <- do.call(substitute, list(j, list(mean = quote(median))))
mc[["j"]] <- j
mc[[1]] <- quote(data.table:::`[.data.table`)
eval.parent(mc)
}
class(a) <- c('dtsurvey', class(a))
a[, mean(v1)]
#> [1] 2
b[, mean(v1)]
#> [1] 4
由 reprex package (v0.3.0)
于 2020-10-08 创建
或者:
"[.dtsurvey" <- function(x, i, j, by, ...){
mc <- match.call()
mc[["j"]] <- do.call(substitute, list(substitute(j), list(mean = quote(median))))
mc[[1]] <- quote(`[`)
mc[[2]] <- substitute(as.data.table(x))
eval.parent(mc)
}
我正在尝试将 data.table
扩展到 speed up/standardize analyses of complex survey designs。为此,我尝试在 [.data.table
之上添加一个光层,在其中拦截 j
中的调用,并在某些情况下替换操作(例如 mean
到 median
) 当需要特殊测量类型命令时(或者当不需要特殊命令时使用普通函数以利用 data.table
的 geforce 类型优化)。
根据我对 s3 dispatch 的部分理解,NextMethod
应该是这里合适的函数,但它似乎将 j
作为符号 j
传递(例如 a[, j]
而不是与 data.table 的 NSE 奇怪地交互的 a[, median(v1)]
。我已经尝试过带有 do.call 的版本,但无法通过一些无限递归废话(do.call('[', ...)
将无休止地发送 [.dtsurvey
)
是否有一种简洁的方法来调整参数并将其传递给 data.table
?在下面的玩具示例中,我希望调用 return 列 v1
的 median
,即使初始操作是 mean
.
library('data.table')
a = data.table(v1 = 1:10)
b = copy(a)
"[.dtsurvey" <- function(x, i, j, by, ...){
j = substitute(j)
print(j)
if(j[[1]] == 'mean') j[[1]] = quote(median)
print(j)
NextMethod(`[`, x)
}
class(a) <- c('dtsurvey', class(a))
a[, mean(v1)]
#> mean(v1)
#> median(v1)
#> Error in `[.data.table`(a, , mean(v1)): j (the 2nd argument inside [...]) is a single symbol but column name 'j' is not found. Perhaps you intended DT[, ..j]. This difference to data.frame is deliberate and explained in FAQ 1.1.
由 reprex package (v0.3.0)
于 2020-10-08 创建我认为您无法在此处利用 NextMethod,据我所知,它会考虑传递的参数。这是一种方法:
library(data.table)
a = data.table(v1 = c(1,2,9))
b = copy(a)
"[.dtsurvey" <- function(x, i, j, by, ...){
mc <- match.call()
j <- substitute(j)
j <- do.call(substitute, list(j, list(mean = quote(median))))
mc[["j"]] <- j
mc[[1]] <- quote(data.table:::`[.data.table`)
eval.parent(mc)
}
class(a) <- c('dtsurvey', class(a))
a[, mean(v1)]
#> [1] 2
b[, mean(v1)]
#> [1] 4
由 reprex package (v0.3.0)
于 2020-10-08 创建或者:
"[.dtsurvey" <- function(x, i, j, by, ...){
mc <- match.call()
mc[["j"]] <- do.call(substitute, list(substitute(j), list(mean = quote(median))))
mc[[1]] <- quote(`[`)
mc[[2]] <- substitute(as.data.table(x))
eval.parent(mc)
}