我正在努力高效地执行两个数据帧之间的“关闭”日期匹配。这个问题使用plyr
软件包中的idata.frame
来探索解决方案,但我也会对其他建议的解决方案感到非常满意。R - 加速近似日期匹配。 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")
在实际的数据,sampleticker
是超过30,000行40列,samplereport
25列近30万行。
我想这样做是为了让在sampleticker
每一行与samplereport
最接近的日期匹配发生在sampleticker
之日起合并,合并这两个数据帧。我通过在股票字段上进行简单合并,按升序排序,然后选择股票和日期的唯一组合,解决了过去类似的问题。但是,由于此数据集的大小,合并速度非常快。
据我所知,merge
不允许这种近似匹配。我看到一些使用findInterval
的解决方案,但由于日期之间的距离会有所不同,我不确定我是否可以指定适用于所有行的间隔。
继另一篇文章here,我写了下面的代码在每一行使用adply
并执行连接:
library(plyr)
merge<-adply(sampleticker,1,function(x){
y<-subset(samplereport,ticker %in% x$ticker & rdate > x$date)
y[which.min(y$rdate),]
}))
这工作得很好:为样本数据,我得到了下面,这是我想要的。
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
然而,由于代码执行30,000子集化操作,这是极其缓慢:我跑了上面的查询时间超过一天终于杀死它。
我看到here plyr 1.0有一个结构,idata.frame
,它通过引用调用数据帧,大大加快了子集操作。但是,我不能让下面的代码工作:
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),]
})
我得到的错误
Error in list_to_dataframe(res, attr(.data, "split_labels")) :
Results must be all atomic, or all data frames
这对我来说很有意义,因为操作返回的idata.frame
(我认为)。但是,改变最后一行:
as.data.frame(y[which.min(y$rdate),])
也抛出一个错误:
Error in `[.data.frame`(x$`_data`, x$`_rows`, x$`_cols`) :
undefined columns selected.
注意,呼吁普通的旧samplereport
返回原始数据帧as.data.frame
,符合市场预期。
我知道idata.frame
是实验性的,所以我不一定期望它能正常工作。但是,如果任何人有关于如何解决这个问题的想法,我将不胜感激。或者,如果任何人都可以提出更有效运行的完全不同的方法,那就太棒了。
马特
UPDATE Data.table是去的正确方法。见下文。
而且,您还可以通过输入负数而不是“Inf”来限制卷的数量。神奇的东西! – Matt 2013-03-06 22:29:59
非常好。感谢您发布此信息。 – 2013-03-06 22:35:18