13

带有数据的表(它是一个 data.table 对象),如下所示:

      date         stock_id logret
   1: 2011-01-01        1  0.001
   2: 2011-01-02        1  0.003
   3: 2011-01-03        1  0.005
   4: 2011-01-04        1  0.007
   5: 2011-01-05        1  0.009
   6: 2011-01-06        1  0.011
   7: 2011-01-01        2  0.013
   8: 2011-01-02        2  0.015
   9: 2011-01-03        2  0.017
  10: 2011-01-04        2  0.019
  11: 2011-01-05        2  0.021
  12: 2011-01-06        2  0.023
  13: 2011-01-01        3  0.025
  14: 2011-01-02        3  0.027
  15: 2011-01-03        3  0.029
  16: 2011-01-04        3  0.031
  17: 2011-01-05        3  0.033
  18: 2011-01-06        3  0.035

以上可以创建为:

DT = data.table(
   date=rep(as.Date('2011-01-01')+0:5,3) , 
   stock_id=c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3),
  logret=seq(0.001, by=0.002, len=18));

setkeyv(DT,c('stock_id','date'))

当然,真正的表格更大,有更多的 stock_id 和日期。旨在重塑此数据表,以便我可以对所有 stockid log_returns 及其相应的 log_returns 进行回归,滞后 1 天(或周末的前交易日)。

最终结果如下所示:

      date         stock_id logret lagret
   1: 2011-01-01        1  0.001    NA
   2: 2011-01-02        1  0.003    0.001
   3: 2011-01-03        1  0.005    0.003
   ....
  16: 2011-01-04        3  0.031  0.029
  17: 2011-01-05        3  0.033  0.031
  18: 2011-01-06        3  0.035  0.033

我发现这个数据结构真的很难在不混淆我的股票的情况下构建。

4

3 回答 3

21

由于亚历克斯的评论,只是一些额外的注释。你很难理解这里发生了什么的原因是很多事情都是在一行中完成的。因此,分解事物总是一个好主意。

我们真正想要什么?我们想要一个新列lagret,在 data.table 中添加一个新列的语法如下:

DT[, lagret := xxx]

wherexxx必须在 column 中填入您想要的任何内容lagret。因此,如果我们只想要一个为我们提供行的新列,我们可以调用

DT[, lagret := seq(from=1, to=nrow(DT))]

在这里,我们实际上想要 的滞后值logret,但我们必须考虑到这里有很多股票。这就是我们进行自连接的原因,即我们DT通过列stock_id和将 data.table 与自身连接起来date,但是由于我们想要每只股票的先前值,所以我们使用date-1。请注意,我们必须先设置键才能进行这样的连接:

setkeyv(DT,c('stock_id','date'))
DT[list(stock_id,date-1)]
    stock_id       date logret
 1:        1 2010-12-31     NA
 2:        1 2011-01-01  0.001
 3:        1 2011-01-02  0.003
 4:        1 2011-01-03  0.005
 5:        1 2011-01-04  0.007
 6:        1 2011-01-05  0.009
...

如您所见,我们现在拥有了我们想要的东西。logret现在滞后一个周期。但我们实际上希望在 中的新列lagret中使用它DT,所以我们只需通过调用 [[3L]] 来获取该列(这意味着没有别的意思,然后给我第三列)并将这个新列命名为lagret

DT[,lagret:=DT[list(stock_id,date-1),logret][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-04        1  0.007  0.005
 5: 2011-01-05        1  0.009  0.007
...

这已经是正确的解决方案。在这个简单的例子中,我们不需要,roll=TRUE因为日期没有间隔。然而,在一个更现实的例子中(如上所述,例如当我们有周末时),可能会有差距。DT因此,让我们通过删除第一只股票中的两天来做一个现实的例子:

DT <- DT[-c(4, 5)]
setkeyv(DT,c('stock_id','date'))
DT[,lagret:=DT[list(stock_id,date-1),logret][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-06        1  0.011     NA
 5: 2011-01-01        2  0.013     NA
...

如您所见,问题在于我们没有 1 月 6 日的值。这就是我们使用的原因roll=TRUE

DT[,lagret:=DT[list(stock_id,date-1),logret,roll=TRUE][[3L]]]
          date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-06        1  0.011  0.005
 5: 2011-01-01        2  0.013     NA
...

只需查看有关如何roll=TRUE工作的文档即可。简而言之:如果找不到之前的值(这里logret是 1 月 5 日),它只需要最后一个可用的值(这里是 1 月 3 日)。

于 2012-09-11T09:52:44.873 回答
4

更新:

在 data.table 的当前开发版本 v1.9.5 中,实现shift()# 965,目前有两种类型type = "lag"(默认)和type = "lead". 有关?shift使用的更多信息,请参阅。

有了这个,我们可以简单地做:

# type="lag" may be omitted, as it is the default.
require(data.table) ## 1.9.5+
DT[, lagret := shift(logret, 1L, type="lag"), by=stock_id]
#           date stock_id logret lagret
#  1: 2011-01-01        1  0.001     NA
#  2: 2011-01-02        1  0.003  0.001
#  3: 2011-01-03        1  0.005  0.003
#  4: 2011-01-04        1  0.007  0.005
#  5: 2011-01-05        1  0.009  0.007
#  6: 2011-01-06        1  0.011  0.009
#  7: 2011-01-01        2  0.013     NA
#  8: 2011-01-02        2  0.015  0.013
#  9: 2011-01-03        2  0.017  0.015
# 10: 2011-01-04        2  0.019  0.017
# 11: 2011-01-05        2  0.021  0.019
# 12: 2011-01-06        2  0.023  0.021
# 13: 2011-01-01        3  0.025     NA
# 14: 2011-01-02        3  0.027  0.025
# 15: 2011-01-03        3  0.029  0.027
# 16: 2011-01-04        3  0.031  0.029
# 17: 2011-01-05        3  0.033  0.031
# 18: 2011-01-06        3  0.035  0.033
于 2015-01-07T19:26:57.807 回答
2

感谢 Matthew Dowle 的建议,我能够使用以下内容:

DT[,lagret:=DT[list(stock_id,date-1),logret,roll=TRUE][[3L]]]

结果是:

             date stock_id logret lagret
 1: 2011-01-01        1  0.001     NA
 2: 2011-01-02        1  0.003  0.001
 3: 2011-01-03        1  0.005  0.003
 4: 2011-01-04        1  0.007  0.005
 5: 2011-01-05        1  0.009  0.007
 6: 2011-01-06        1  0.011  0.009
 7: 2011-01-01        2  0.013     NA
 8: 2011-01-02        2  0.015  0.013
 9: 2011-01-03        2  0.017  0.015
10: 2011-01-04        2  0.019  0.017
11: 2011-01-05        2  0.021  0.019
12: 2011-01-06        2  0.023  0.021
13: 2011-01-01        3  0.025     NA
14: 2011-01-02        3  0.027  0.025
15: 2011-01-03        3  0.029  0.027
16: 2011-01-04        3  0.031  0.029
17: 2011-01-05        3  0.033  0.031
18: 2011-01-06        3  0.035  0.033
于 2012-07-12T13:38:49.600 回答