如何在不破坏data.table的自定义评估的情况下调整[.data.table`中的j?

问题描述

我正在尝试将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)
}