2013-01-10 164 views
1

我有两个非常大的数据帧(50MM +行),我需要对它们运行一些计算。我开发了以下循环,但运行速度太慢。我尝试使用应用程序和其他方法,但我无法让他们工作。R循环运行速度太慢

#### 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) 
} 

回答

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)) 

使用从包plyr功能ddply()根据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倍。

+0

...如果'plyr'有这个效果,你可以很容易地使用'data.table'加快速度...... –

1

使用第二个ID,以从查找参考时间,并减去活动时间,为您的数据上面绝对时间差小于5

okIds <- df2$id2[abs(as.numeric(dt)) < 5] 

dt <- df2$time2 - df$time[df2$id] 

然后选择事件id

这些制表,并添加到您的原始数据帧

df$within5 <- tabulate(okIds, max(df$id)) 

这依赖于ID s是顺序整数(如果不是,使它们成为factor(),然后使用编码结果的整数)并且速度非常快。