我正在使用data.table包来返回j
表达式中的函数闭包列表,作为stats包中approxfun
函数的输出。基本上,在每个Date上,我都希望有一个闭包,它允许我根据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”分组创建的组中的最后一个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缺少的东西?
先谢谢您的帮助
最佳答案
是的,典型的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