2017-08-17 60 views
4

我正在使用data.table包來返回j表達式中的函數關閉列表,作爲approxfun函數從stats包中輸出的表達式。基本上,在每個日期,我想要一個閉包,它允許我根據approxfun確定的任意xval來計算任意yval。處理data.table中的閉包

但是,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是最後的 yval在由'by'分組創建的組中由非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)) 

還有其他人遇到過這個問題嗎?這是我失蹤的基地R或我失蹤data.table?

在此先感謝您的幫助

回答

5

是的,典型的data.table參考VS複製常見問題。這按預期工作:

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