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

dot*_*mba 4 r r-s3 data.table

我正在尝试扩展data.table加速/标准化复杂调查设计的分析。为此,我试图[.data.table在我拦截调用的位置上添加一个轻层,j并在某些情况下在需要特殊调查类型命令时替换操作(例如meanto median)(或在特殊情况下使用正常功能不需要利用data.table的 geforce 类型优化)。

基于我对 s3 调度的部分理解,NextMethod这里应该是合适的函数,但它似乎j作为符号传递j(例如,a[, j]而不是a[, median(v1)]它与 data.table 的 NSE 奇怪地交互。我已经尝试过使用 do.call 的版本,但不能不要通过一些无限递归的废话(do.call('[', ...)将无休止地发送[.dtsurvey

有没有一种干净的方法来调整参数并将其传递给data.table?在下面的例子玩具,我想有调用返回median列的v1,即使初始操作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.
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.3.0)于 2020 年 10 月 8 日创建

Moo*_*per 5

我认为您无法在这里利用 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
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.3.0)于 2020 年 10 月 8 日创建

或者:

"[.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)
}
Run Code Online (Sandbox Code Playgroud)