2013-01-10 191 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(),然後使用編碼結果的整數)並且速度非常快。