R数据表包中时间序列的有效处理

时间:2013-11-22 09:25:06

标签: r time-series data.table

非常感谢你的评论/回答。

背景信息:我有一个包含十几个国家/地区掉期汇率每日价格的大型数据表。列是[ID,Date,X1Y,X2Y,X3Y ... X30Y],其中X..Y是表示收益率曲线部分的列(例如,X1Y是1年交换,X3Y是3年交换)。这两个键是 ID (例如“AUD”,“GBP”)和 Date (例如“2001-04-13”,“2001-04-16”)。

虚拟数据:

set.seed(123)
dt <- cbind(ID=rep(c("AUD","GBP"),c(100,100)),X1Y=rnorm(200),X2Y=rnorm(200),X3Y=rnorm(200))
dt <- data.table(dt)
dt[,Date := seq(from=as.IDate("2013-01-01"), by="1 day", length.out=100)]
setkeyv(dt,c("ID","Date"))

问题1: 首先生成一些虚拟信号。如果有100列具有相当复杂的信号生成公式,在单独的函数中编写genSig(X1Y),那么语法是什么?这就是我的意思,只使用3列和一些无意义的公式:

dt[,SIG1  :=c(0, diff(X1Y ,1)),by="ID"]
dt[,SIG2  :=c(0, diff(X2Y ,1)),by="ID"]
dt[,SIG3  :=c(0, diff(X3Y ,1)),by="ID"]

问题2: 根据“月中”推进列。例如,使用SIG列,我想在每个月的15日之后做出与15日信号相同的所有内容,直到下个月的15日。棘手的是,实际数据只包含交易日,所以如果是周末/假日,有些月份不会有15日。另一个问题是使用有效的语法,我可以在每个月的开始使用循环(我知道..)来实现类似的东西,只是为了表明我的意思:

for (i in 2:length(dt$Date)){
  if(as.POSIXlt(dt[i,]$Date)$mon == as.POSIXlt(dt[i-1,]$Date)$mon){
    dt[i, SIG1 := dt[i-1,SIG1]] 
    dt[i, SIG2 := dt[i-1,SIG2]] 
    dt[i, SIG3 := dt[i-1,SIG3]] 
  }
}

我无法弄清楚如何处理“月中”问题,因为它可能会落在15或16或17日。与问题1一样,如果有一种智能方式可以插入/更新多个/十几列,我们将不胜感激。

2 个答案:

答案 0 :(得分:2)

就问题2而言,您可以使用滚动连接:

# small sample to demonstrate
dt = data.table(date = as.Date(c('2013-01-01', '2013-01-15', '2013-01-17', '2013-02-14', '2013-02-17'), '%Y-%m-%d'), val = 1:5)
dt
#         date val
#1: 2013-01-01   1
#2: 2013-01-15   2
#3: 2013-01-17   3
#4: 2013-02-14   4
#5: 2013-02-17   5

setkey(dt, date)
midmonth = seq(as.Date('2013-01-15', '%Y-%m-%d'),
               as.Date('2013-12-15', '%Y-%m-%d'),
               by = '1 month')

dt[, flag := 0]
dt[J(midmonth), flag := 1, roll = -Inf]
dt
#         date val flag
#1: 2013-01-01   1    0
#2: 2013-01-15   2    1
#3: 2013-01-17   3    0
#4: 2013-02-14   4    0
#5: 2013-02-17   5    1

现在您可以cumsum flag获取您想要的分组,例如做:

dt[, val1 := val[1], by = cumsum(flag)]
dt
#         date val flag val1
#1: 2013-01-01   1    0    1
#2: 2013-01-15   2    1    2
#3: 2013-01-17   3    0    2
#4: 2013-02-14   4    0    2
#5: 2013-02-17   5    1    5

答案 1 :(得分:1)

# problem 1
nsig <- 3L
csig <- 1:nsig+1L
newcols <- paste('SIG',1:nsig,sep='')
dt[,(newcols):=0]
for (j in csig) set(dt,j=j+nsig+1L,value=c(0, diff(dt[[j]],1)))

在看了@ eddi的回答之后,我发现set对问题2没那么有用。这就是我要做的事情:

dt[,(newcols):=lapply(newcols,function(x) get(x)[1]),by=list(ID,month(Date-14))]

根据this answer,您可以通过这种方式从日期中减去天数。


除了。 Cbinding矢量构成一个矩阵。在您的示例中,您有一个字符矩阵。我想你在找......

# Creating better data...
set.seed(123)
dt <- data.table(ID=rep(c("AUD","GBP"),c(100,100)),
  X1Y=rnorm(200),X2Y=rnorm(200),X3Y=rnorm(200),
  Date=seq(from=as.IDate("2013-01-01"), by="1 day", length.out=100))