【问题标题】:Handling of closures in data.table处理 data.table 中的闭包
【发布时间】:2018-01-25 22:30:00
【问题描述】:

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

但是,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))

j 表达式的上下文中评估函数'afun' 时,会打印'yval' 的正确值。但是,当我在评估第一个函数之后返回时,返回的 yval 是由 approxfun 未创建的函数的“by”分组创建的组中的 last yval (approxfun 创建的所有闭包都按预期工作)。

我怀疑这与我在惰性评估中缺少的东西有关。我使用“强制”功能尝试了下面的附加代码,但没有成功。

 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))

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

提前感谢您的帮助

【问题讨论】:

    标签: r data.table closures


    【解决方案1】:

    是的,典型的 data.table 参考与复制常见问题解答。这按预期工作:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 2014-09-26
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多