Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R-加速近似日期匹配。伊达塔,框架?_R_Data.table_Plyr_Subset - Fatal编程技术网

R-加速近似日期匹配。伊达塔,框架?

R-加速近似日期匹配。伊达塔,框架?,r,data.table,plyr,subset,R,Data.table,Plyr,Subset,我正在努力高效地在两个数据帧之间执行“结束”日期匹配。这个问题探索了一个使用plyr包中的idata.frame的解决方案,但我也很乐意使用其他建议的解决方案 这是两个数据帧的一个非常简单的版本: sampleticker<-data.frame(cbind(ticker=c("A","A","AA","AA"), date=c("2005-1-25","2005-03-30","2005-02-15","2005-04-21"))) sampleticker$date<-as.

我正在努力高效地在两个数据帧之间执行“结束”日期匹配。这个问题探索了一个使用
plyr
包中的
idata.frame
的解决方案,但我也很乐意使用其他建议的解决方案

这是两个数据帧的一个非常简单的版本:

sampleticker<-data.frame(cbind(ticker=c("A","A","AA","AA"),
  date=c("2005-1-25","2005-03-30","2005-02-15","2005-04-21")))
sampleticker$date<-as.Date(sampleticker$date,format="%Y-%m-%d")

samplereport<-data.frame(cbind(ticker=c("A","A","A","AA","AA","AA"),
  rdate=c("2005-2-15","2005-03-15","2005-04-15",
  "2005-03-01","2005-04-20","2005-05-01")))
samplereport$rdate<-as.Date(samplereport$rdate,format="%Y-%m-%d")
这非常有效:对于示例数据,我得到了下面的结果,这就是我想要的

   date       ticker      rdate
 1 2005-01-25  A          2005-02-15
 2 2005-03-30  A          2005-04-15
 3 2005-02-15  AA         2005-03-01
 4 2005-04-21  AA         2005-05-01
但是,由于代码执行了30000多个子集操作,因此速度非常慢:在最终终止之前,我运行了上述查询一天多

我看到PLYR1.0有一个结构,
idata.frame
,它通过引用调用dataframe,大大加快了子集操作。但是,我无法使以下代码正常工作:

isamplereport<-idata.frame(samplereport)
adply(sampleticker,1,function(x){
  y<-subset(isamplereport,isamplereport$ticker %in% x$ticker & 
    isamplereport$rdate > x$date)
  y[which.min(y$rdate),]
})
这对我来说很有意义,因为该操作返回一个
idata.frame
(我假设)。但是,将最后一行更改为:

as.data.frame(y[which.min(y$rdate),]) 
还抛出一个错误:

Error in `[.data.frame`(x$`_data`, x$`_rows`, x$`_cols`) : 
undefined columns selected.
请注意,在普通的旧
sampleport
上调用
as.data.frame
,将返回原始数据帧,这与预期的一样

我知道,
idata.frame
是实验性的,所以我不一定期望它能正常工作。但是,如果有人知道如何解决这个问题,我将不胜感激。或者,如果有人能提出一种完全不同的方法,可以更有效地运行,那就太棒了

马特


更新Data.table是正确的方法。请参见下文。

这里是一个基于
数据表的解决方案,它可能比您当前使用的解决方案工作得更好:

library(data.table)
ST <- data.table(sampleticker, key="ticker")
SR <- data.table(samplereport, key="ticker")
SR <- SR[with(SR, order(ticker, rdate)),] # rdates need to be in increasing order

SR[ST, list(date = date,
            rdate = rdate[match(TRUE, (rdate > date))]), ]
     ticker       date      rdate
[1,]      A 2005-01-25 2005-02-15
[2,]      A 2005-03-30 2005-04-15
[3,]     AA 2005-02-15 2005-03-01
[4,]     AA 2005-04-21 2005-05-01
库(data.table)

ST下面是一个解决方案,它继承了Matthew Dowle的观点,即这是应用
数据的自然场所。table
roll=TRUE
参数


如果你要使用它,有一条皱纹需要熨平
roll=TRUE
的设计是,当没有找到键的最后一列(此处为日期)的精确匹配时,将向前滚动最近的前一个日期的值。但是,您想要的是相反的(即使存在精确匹配,您仍然需要下一个可用日期的值)

第一次尝试可能是按
“ticker”
排序,按
“rdate”
反向排序,并与结果重新排序的
SR
合并。这是可行的,除了
数据。table
不允许按相反顺序排序:按
键控“rdate”
强制该列按升序排序。(
data.table
需要这样做,以实现它所设计的快速匹配和连接)

我下面的解决方案是在两个data.tables中创建一个新列--“rnd”
,用于“反向数字日期”,其值是通过执行
-as.numeric(date)
形成的。这将为每个日期指定一个唯一的值。此外,由于这些值已乘以
-1
按升序排序具有按降序排序日期的效果

(另一个细节:因为你不想要精确的匹配,而总是想要当前日期之后的下一个日期,所以我从sampleticker的
rnd
中减去
1
,这达到了预期的效果。为了确认它的工作是否正确,我稍微编辑了你的示例数据,以包含一个可能的精确匹配(
“2005-1-25”
),不应由合并选择)

#创建示例数据表
库(数据表)

ST多亏了Matthew Dowle和他在data.table中添加的向后滚动和向前滚动的功能,现在执行这种合并变得简单多了

ST <- data.table(sampleticker)
SR <- data.table(samplereport)
setkey(ST,ticker,date)
SR[,mergerdate:=rdate]
setkey(SR,ticker,mergerdate)
merge<-SR[ST,roll=-Inf]
setnames(merge,"mergerdate","date")

#    ticker       date      rdate
# 1:      A 2005-01-25 2005-02-15
# 2:      A 2005-03-30 2005-04-15
# 3:     AA 2005-02-15 2005-03-01
# 4:     AA 2005-04-21 2005-05-01

ST
roll=TRUE
就是为这个目的而设计的。要得到最接近的after-then可能是
X[Y,roll=TRUE,which=TRUE]+1]
,或者将其反转并执行
Y[X,roll=TRUE]
。但是下一个after要求非常罕见。实际上
mult=“last”
DT[J(日期,23:00),roll=TRUE]
通常更好。我实际上会大量使用“下一个之后”的要求;在事件发生后选择第一条记录来衡量对事件的响应是很常见的。我会尝试使用
roll=TRUE
来达到正确的效果。我的初步建议(可能不正确)尝试给了我相反的结果:
sampleport
是距离
sampleticker
最近的,但是相反的过程会给我
sampleport
中的所有记录以及一堆NAs,这绝对不是我想要的。我必须了解更多关于data.table的信息,因为它看起来非常有用。@Matt--澄清很有帮助。由于您也在查看
roll=TRUE
,我将花时间发布一个我找到的使用它的解决方案。请让我知道它对您的数据是否有效。谢谢Josh。我认为您上面的解决方案也有效;我非常确定,在我开始玩
roll=TRUE
之前,它一直在工作,并且然后我把它搞砸了。我现在要尝试恢复你的解决方案。我肯定也会对
roll=TRUE
解决方案感兴趣。它更简洁,而且似乎要快得多。这也是一个很好的解决方案,它的运行速度比公认的解决方案快得多。非常好!我没有完全检查它,但我得到了它概念。好的,你们说服了我:
[.data.table
需要一个新的参数来回滚下一个观察值,不是吗。顺便说一句,这是一个简单的内部切换。选项:
revroll
rollback
rollbacktofirst
next
after
或一些组合?或者不是新的参数,
roll=-1 | 0 | 1
表示在| equal | previous
之后的
,其中
TRUE
FALSE
不需要更改,因为它们分别映射到previous和equal
library(data.table)
ST <- data.table(sampleticker, key="ticker")
SR <- data.table(samplereport, key="ticker")
SR <- SR[with(SR, order(ticker, rdate)),] # rdates need to be in increasing order

SR[ST, list(date = date,
            rdate = rdate[match(TRUE, (rdate > date))]), ]
     ticker       date      rdate
[1,]      A 2005-01-25 2005-02-15
[2,]      A 2005-03-30 2005-04-15
[3,]     AA 2005-02-15 2005-03-01
[4,]     AA 2005-04-21 2005-05-01
# Add some columns to both data.tables
ST$alpha <- letters[seq_len(nrow(ST))]
SR$n     <- seq_len(nrow(SR))
SR$ALPHA <- LETTERS[seq_len(nrow(SR))]

# Perform a merge that includes the whole rows from samplereport
# corresponding to the selected rdate
RES <- SR[ST, cbind(date, .SD[match(TRUE,(rdate>date)),-1]), ]

# Merge res (containing the selected rows from samplereport) back together
# with sampleticker
keycols <- c("ticker", "date")
setkeyv(RES, keycols)
setkeyv(ST, keycols)
ST[RES]
#      ticker       date alpha      rdate n ALPHA
# [1,]      A 2005-01-25     a 2005-02-15 1     A
# [2,]      A 2005-03-30     b 2005-04-15 3     C
# [3,]     AA 2005-02-15     c 2005-03-01 4     D
# [4,]     AA 2005-04-21     d 2005-05-01 6     F
# Create sample data.tables
library(data.table)

ST <- data.table(ticker = c("A","A","AA","AA"),
                 date = as.Date(c("2005-1-25","2005-03-30","2005-02-15",
                                  "2005-04-21"), format="%Y-%m-%d"),
                 alpha = letters[1:4])    

SR <- data.table(ticker = c("A","A","A","AA","AA","AA"),
                 rdate = as.Date(c("2005-1-25","2005-03-15","2005-04-15",
                                   "2005-03-01","2005-04-20","2005-05-01"), 
                                   format="%Y-%m-%d"),
                 ALPHA = LETTERS[1:6])
# Create a "reverse numerical date" column, which will uniquely
# identify date, and allow them to be sorted in reverse temporal order
ST$rnd <- -(as.numeric(ST$date) + 1)
SR$rnd <- -(as.numeric(SR$rdate))

# key (and thus sort) both data.tables by ticker and "reverse numerical date"
keycols <- c("ticker", "rnd")
setkeyv(ST, keycols)
setkeyv(SR, keycols)

# The syntax of the merge is now as simple as can be
res <- SR[ST, roll=TRUE]

# Finally, put the results back in temporal order, and pretty up the column order
setkeyv(res, c("ticker", "date"))
setcolorder(res, c("ticker", "date", "rdate", "alpha", "ALPHA", "rnd"))
res
#      ticker       date      rdate alpha ALPHA    rnd
# [1,]      A 2005-01-25 2005-03-15     a     B -12809
# [2,]      A 2005-03-30 2005-04-15     b     C -12873
# [3,]     AA 2005-02-15 2005-03-01     c     D -12830
# [4,]     AA 2005-04-21 2005-05-01     d     F -12895
ST <- data.table(sampleticker)
SR <- data.table(samplereport)
setkey(ST,ticker,date)
SR[,mergerdate:=rdate]
setkey(SR,ticker,mergerdate)
merge<-SR[ST,roll=-Inf]
setnames(merge,"mergerdate","date")

#    ticker       date      rdate
# 1:      A 2005-01-25 2005-02-15
# 2:      A 2005-03-30 2005-04-15
# 3:     AA 2005-02-15 2005-03-01
# 4:     AA 2005-04-21 2005-05-01