是否可以将函数对象作为元素

时间:2016-04-12 10:34:17

标签: r data.table

简短回答:是的,请参阅接受的回复。

我有两个data.table

stocks = data.table(Ticker = c('xx','xx','yy','yy'), Date = c(as.IDate("2000-01-01"), as.IDate("2000-01-02")), t = c(1.8, 3.5))
   Ticker       Date   t
1:     xx 2000-01-01 1.8
2:     xx 2000-01-02 3.5
3:     yy 2000-01-01 1.8
4:     yy 2000-01-02 3.5
tt = data.table(Date = c(as.IDate("2000-01-01"), as.IDate("2000-01-02")), t0 = c(1,2), t1 = c(2,3), t2 = c(3,4), y0 = c(10, 20), y1 = c(-20, -30), y2 = c(33,44))
         Date t0 t1 t2 y0  y1 y2
1: 2000-01-01  1  2  3 10 -20 33
2: 2000-01-02  2  3  4 20 -30 44

对于stocks中的每一行,我想根据y中值的线性插值找到给定t的近似tt

zz = tt[stocks, on = 'Date']
zz[, y.approx := approx(c(t0,t1,t2), c(y0,y1,y2), t)$y, by = 'Date,Ticker']
         Date t0 t1 t2 y0  y1 y2 Ticker   t y.approx
1: 2000-01-01  1  2  3 10 -20 33     xx 1.8      -14
2: 2000-01-02  2  3  4 20 -30 44     xx 3.5        7
3: 2000-01-01  1  2  3 10 -20 33     yy 1.8      -14
4: 2000-01-02  2  3  4 20 -30 44     yy 3.5        7

问题是这样做会有很多重复的计算。理想情况下,我想为每天定义approxfun并将其应用于stocks中的每一行。但是数据表不能将函数对象作为其元素。

tt[, ff := approxfun(c(t0,t1,t2), c(y0,y1,y2)), by = Date]
Error in `[.data.table`(tt, , `:=`(ff, approxfun(c(t0, t1, t2), c(y0,  : 
  j evaluates to type 'closure'. Must evaluate to atomic vector or list.

我的问题是:

  1. 有没有比在每一行上做approx更好的方法(而且速度慢)?
  2. 数据表是否可以将函数对象作为其元素?

3 个答案:

答案 0 :(得分:6)

$ java -help … -cp <class search path of directories and zip/jar files> -classpath <class search path of directories and zip/jar files> A : separated list of directories, JAR archives, and ZIP archives to search for class files. 中存储函数非常简单 - 只需将它们放在列表中即可:

lib

答案 1 :(得分:5)

如下:

> zz
         Date t0 t1 t2 y0  y1 y2 Ticker   t
1: 2000-01-01  1  2  3 10 -20 33     xx 1.8
2: 2000-01-02  2  3  4 20 -30 44     xx 3.5
3: 2000-01-01  1  2  3 10 -20 33     yy 1.8
4: 2000-01-02  2  3  4 20 -30 44     yy 3.5

> zz[t0<=t & t<=t1, y.approx:={a=(t-t0)/(t1-t0); y0+a*(y1-y0)}]
> zz
         Date t0 t1 t2 y0  y1 y2 Ticker   t y.approx
1: 2000-01-01  1  2  3 10 -20 33     xx 1.8      -14
2: 2000-01-02  2  3  4 20 -30 44     xx 3.5       NA
3: 2000-01-01  1  2  3 10 -20 33     yy 1.8      -14
4: 2000-01-02  2  3  4 20 -30 44     yy 3.5       NA

> zz[t1<=t & t<=t2, y.approx:={a=(t-t1)/(t2-t1); y1+a*(y2-y1)}]
> zz
         Date t0 t1 t2 y0  y1 y2 Ticker   t y.approx
1: 2000-01-01  1  2  3 10 -20 33     xx 1.8      -14
2: 2000-01-02  2  3  4 20 -30 44     xx 3.5        7
3: 2000-01-01  1  2  3 10 -20 33     yy 1.8      -14
4: 2000-01-02  2  3  4 20 -30 44     yy 3.5        7
> 

不知道你需要它有多普遍(你真正有多少列)。但是值得尝试像这样进行向量化以逐行保存函数调用。对于时间增量的数量for循环的几次迭代(在这种情况下为2)应该比按行循环更快(让我们知道你是否采用这种方式并且需要为每个时间增量动态生成查询)。

答案 2 :(得分:2)

我们可以使用全局函数列表和超级赋值运算符来破解它:

x <- list();
invisible(tt[,{ x[[as.character(Date)]] <<- approxfun(c(t0,t1,t2),c(y0,y1,y2)); 0; },Date]);
x;
## $`2000-01-01`
## function (v)
## .approxfun(x, y, v, method, yleft, yright, f)
## <bytecode: 0x602762000>
## <environment: 0x603118610>
##
## $`2000-01-02`
## function (v)
## .approxfun(x, y, v, method, yleft, yright, f)
## <bytecode: 0x602762000>
## <environment: 0x60312c9d0>
##
stocks[,y.approx:=x[[as.character(Date)]](t),Date];
##    Ticker       Date   t y.approx
## 1:     xx 2000-01-01 1.8      -14
## 2:     xx 2000-01-02 3.5        7
## 3:     yy 2000-01-01 1.8      -14
## 4:     yy 2000-01-02 3.5        7