处理data.table中的闭包

rlh*_*lh2 5 closures r data.table

我正在使用data.table包来返回j表达式中的函数闭包列表,作为approxfunstats包中函数的输出.基本上,在每个Date上,我想要一个闭包,它允许我根据确定的任意xval计算任意yval approxfun.

但是,approxfun仅当传递给函数的x的至少两个唯一值时才有效.在只有一个x的唯一值的情况下,我想返回一个返回y的唯一值的函数.

在下面的代码,我执行该步骤通过检查.N值并返回取决于是否不同的功能.N就是> 1.

 library(data.table)
 set.seed(10)
 N <- 3
 x <- data.table(Date = Sys.Date() + rep(1:N, each = 3), xval = c(0, 30, 90), yval = rnorm(N * 3))
 x <- x[-c(2:3), ]

 ##interpolation happens correctly
 x2 <- x[order(Date, xval), {
     if(.N > 1){
         afun <- approxfun(xval, yval, rule = 1)
     }else{
         afun <- function(v) yval
     }
     print(afun(30))
     list(Date, afun = list(afun))
 }, by = Date]

 ##evaluation does NOT happen correctly, the val used is the last...
 sapply(x2[, afun], do.call, args = list(v = 30))
Run Code Online (Sandbox Code Playgroud)

j表达式的上下文中计算函数"afun"时,将打印"yval"的正确值.但是,当我回过头来评估第一个函数时,返回的yval是由'by'分组创建的组中的最后一个 yval,该函数不是由approxfun(由approxfun工作按预期创建的所有闭包)创建的..

我怀疑这与懒惰评估中缺少的东西有关.我使用'force'函数尝试了下面的附加代码但是没有成功.

 x3 <- x[order(Date, xval), {
      if(.N > 1){
         afun <- approxfun(xval, yval, rule = 1)
     }else{
         fn <- function(x){
             force(x)
             function(v) x
         }
         afun <- fn(yval)
     }
     print(afun(30))
     list(Date, afun = list(afun))
 }, by = Date]

 sapply(x3[, afun], do.call, args = list(v = 30))
Run Code Online (Sandbox Code Playgroud)

还有其他人遇到过这个问题吗?这是我缺少基础R还是我缺少data.table的东西?

在此先感谢您的帮助

Rol*_*and 6

是的,典型的data.table参考与复制FAQ.这按预期工作:

x2 <- x[order(Date, xval), {
  if(.N > 1){
    afun <- approxfun(xval, yval, rule = 1)
  }else{
    fn <- function(){
      #ensure the value is copied
      x <- copy(yval)
      function(v) x
    }
    afun <- fn()
  }
  print(afun(30))
  list(Date, afun = list(afun))
}, by = Date]
#[1] 0.01874617
#[1] 0.2945451
#[1] -0.363676

sapply(x2[, afun], do.call, args = list(v = 30))
#[1]  0.01874617  0.29454513 -0.36367602
Run Code Online (Sandbox Code Playgroud)