2017-03-03 194 views
1

我已經在R中編寫了一個循環,並且希望使其運行速度更快。任務是計算數據幀(tibble)中time列的增量值。皺褶是每個增量應取自上一行,其中level列的值(範圍1-9)大於或等於當前行。我需要運行這約十億行,目前的性能大大低於每秒100萬行。所以我正在尋找至少一個數量級的加速。優化R循環

下面是代碼:

ref <- as.numeric(rep(NA, 9)) # separate reference timestamp per level 
timedelta <- function(level, time) { 
    delta <- time - ref[level] 
    ref[1:level] <<- time 
    delta 
} 
mapply(timedelta, tl$level, tl$time) 

如何作出這樣跑得快?

(我曾問過dplyr的背景下,同樣的問題在How to add flexible delta columns using dplyr?,但我沒能得到我所需要dplyr所以我在這裏再次要求的性能。)

+1

我不完全理解你需要做什麼,但在迭代取決於前一次迭代的結果的情況下,我試試Rcpp – konvas

+0

你是否嘗試過分析代碼以查看瓶頸在哪裏? –

+1

對於大型數據集,您可以嘗試使用data.table(它比dplyr更快)以及foreach(允許您並行運行循環)。如果你發佈一個可重現的例子,你會在這裏得到更好的結果:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Henk

回答

0

我不知道我完全理解你在給出的代碼中做了什麼,但最好的辦法是刪除顯式循環。類似這樣的:

tl$delta <- tl$time - ref[tl$level] 
ref[1:tl$level] <- tl$time 

然後總結你的增量或任何你需要的操作。 R在循環中運行不正常。它喜歡像數據框這樣的大型矩陣。我會給你另一個例子。假設我想計算我的數據框中的哪些客戶每天都在我的酒店住宿,因爲他們的到達和離開。我可以寫一個循環是這樣的:

days<-seq(as.Date("2016-01-01"), as.Date("2016-12-31"), by="days") 
num_guests<-rep(0, length(days)) 
for(d in c(1:length(num_guests))){ 
    for(i in c(1:nrow(guests.df))){ 
     if(guests.df$Arrive_Date[i]<=days[d] & guests.df$Leave_Date[i]>=days[d]){ 
    num_guests[d]=num_guests[d]+1 
} 
} 
} 

此循環策略需要13分鐘到6700位客人在我的數據幀上的i7處理器上運行。或者我可以將其更改爲:

for(d in c(1:length(num_guests))){ 
    guests.df$in_period<-guests.df$Arrive_Date<=days[d] & guests.df$Leave_Date>=days[d] 
    num_guests[d]<-sum(guests.df$in_period) 
} 

第二個循環花了一秒鐘才能運行。