2017-03-03 154 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) 
} 

第二个循环花了一秒钟才能运行。