问题描述
我正在尝试将data.table
扩展到speed up/standardize analyses of complex survey designs。为此,我正在尝试在[.data.table
上添加一个浅层,以拦截j
中的呼叫,并在某些情况下替换该操作(例如,将mean
更改为{ {1}})在需要特殊测量类型命令时(或在不需要特殊命令以利用median
的geforce类型优化的情况下使用常规功能)。
根据我对s3调度的部分理解,data.table
应该是此处的适当功能,但似乎正在将NextMethod
作为符号j
传递(例如j
而不是a[,j]
,它与data.table的NSE产生了怪异的交互。我已经尝试过使用do.call的版本,但无法克服一些无限递归的缺点(a[,median(v1)]
会无休止地调度do.call('[',...)
)
是否有一种干净的方法来调整参数并将其传递给[.dtsurvey
?在下面的玩具示例中,即使初始操作为data.table
,我还是希望该调用返回列median
的{{1}}。
v1
由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,...){
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)
}