我可以避免在向量中进行循环操作吗?

时间:2015-03-19 17:45:03

标签: r for-loop data.table

有没有办法在没有for循环的情况下计算数据表中的第4列(超时)?该列的每一行都使用第i-1行,因此在增加行数时需要花费大量时间。

library(data.table)
dt <- data.table(
id = 1:200, 
timein = cumsum(runif(200,1,6)),
servtime = runif(200,3,4))

dt[,"timeout"] <- dt$timein # initialisation of timeout column

# update column timeout
for(i in 2:200) {
dt$timeout[i] <- max(dt$timein[i], dt$timeout[i-1]) +  dt$servtime[i]
} 

1 个答案:

答案 0 :(得分:3)

我没有在基础R中看到一个简单的方法来使用矢量化运算符来加快速度,但是你可以使用Rcpp来加速操作:

library(Rcpp)
get.timeout <- cppFunction("
NumericVector getTimeout(NumericVector timein, NumericVector servtime) {
  const int n = timein.size();
  NumericVector timeout(n);
  timeout[0] = timein[0];
  for (int i=1; i < n; ++i) {
    timeout[i] = fmax(timein[i], timeout[i-1]) + servtime[i];
  }
  return timeout;
}")

这比使用for循环的解决方案更快:

for.loop <- function(timein, servtime) {
  timeout <- dt$timein
  n <- length(timeout)
  for(i in 2:n) {
    timeout[i] <- max(timein[i], timeout[i-1]) +  servtime[i]
  }
  return(timeout)
}
all.equal(for.loop(dt$timein, dt$servtime), get.timeout(dt$timein, dt$servtime))
# [1] TRUE
library(microbenchmark)
microbenchmark(for.loop(dt$timein, dt$servtime), get.timeout(dt$timein, dt$servtime))
# Unit: microseconds
#                                 expr     min       lq      mean   median       uq     max neval
#     for.loop(dt$timein, dt$servtime) 414.040 429.5315 438.68765 435.4000 445.1185 506.162   100
#  get.timeout(dt$timein, dt$servtime)  22.432  23.9305  28.54934  27.9135  28.6670  97.259   100

对于较大的输入,优势可能会增加。