我有两个非常大的数据帧(50MM +行),我需要对它们进行一些计算。我开发了以下循环,但运行速度太慢。我尝试使用apply和其他方法,但我无法让它们工作。
#### Sample Data
df=data.frame(id=1:10,time=Sys.time()-1:10,within5=NA)
df2=data.frame(id2=c(1,1,1,5,5,10),time2=Sys.time()-c(9,5,2,3,4,6))
#### Loop shows how many results from df2 are within 5 secs of the creation of the ID in df
for (i in 1:length(df$id))
{
temp=df2[df2$id==df$id[i],]
df$within5[i]=sum(abs(as.numeric(difftime(temp$time2,df$time[i],units="secs")))<5)
}
答案 0 :(得分:3)
检查程序的改进,制作更大的样本数据。
df=data.frame(id=1:100,time=Sys.time()-1:100)
df2=data.frame(id2=sample(1:100,300000,replace=T),time2=Sys.time()-sample(1:5,300000,replace=T))
使用包ddply()
中的功能plyr
根据列id2
划分数据。然后将您的函数应用于每个子集。
library(plyr)
df3 <- ddply(df2,"id2",function(x){
data.frame(within5=sum(abs(as.numeric(difftime(x$time2,df$time[df$id==x$id2[1]],units="secs")))<5))})
结果我们获得了新的数据框架。
head(df3)
id2 within5
1 1 3129
2 2 3032
3 3 2935
4 4 3121
5 5 3042
6 6 2426
如果您在原始数据框中需要列within5
,则可以使用函数merge()
。
df4 <- merge(df,df3,by.x="id",by.y="id2",all=T)
使用我的样本数据,这个计算速度提高了10倍。
答案 1 :(得分:1)
使用第二个ID查找参考时间,并从中减去事件时间,对于上面的数据
dt <- df2$time2 - df$time[df2$id]
然后选择绝对时间差小于5的事件ID
okIds <- df2$id2[abs(as.numeric(dt)) < 5]
将这些列表制作,并添加到原始数据框
df$within5 <- tabulate(okIds, max(df$id))
这依赖于id是顺序整数(如果不是,使它们成为factor()
,然后使用整数编码结果)并且非常快。