具有大量案例的for循环的性能

时间:2018-03-26 10:40:58

标签: r performance loops for-loop random

我有88.000个观察结果,用1:

编码
obs <- rep(1,88000)

另外,我有以下功能,其中进行随机实验。将值p与随机数进行比较;根据结果​​,x会改变(+ 1)或保持不变。

rexp <- function(x,p){
  if(runif(1) <= p) return(x + 1)
  return(x)
}

旁边&#34; obs&#34;和&#34; rexp&#34;一个空的数据帧&#34; dat&#34;给出了500行和0列。还有一个占位符&#34;结果&#34;:

dat <- data.frame(row.names = 1:500)
dat$result <- rep(',',500)

我使用以下循环来应用函数&#34; rexp&#34; (对于p = 0.03)向量矢量&#34; obs&#34;并保存&#34; obs&#34;的更改次数。由随机实验引起的结果&#34;结果&#34;在数据框&#34; dat&#34;:

for(i in 1:500){
  x <- sapply(obs,rexp,0.03)
  x <- table(x)
  x <- x[names(x) == 2]
  dat$result[i] <- x
}

现在问题:上面的for-Loop基本上可以工作,但是它的性能非常糟糕。执行需要很长时间,通常循环甚至会卡住。在上面的例子中,只使用了88,000个观测值,与880.000一样工作似乎几乎不可能。我不确定为什么表现如此糟糕。例如,在我的设备上,可以在不到一分钟的时间内完成相同的程序(即使有880.000次观察)。我知道for循环应该在r中被绕过,但我不知道如何执行该过程。如果有任何提示可以解释和改善所描述的循环的性能,我将不胜感激!

1 个答案:

答案 0 :(得分:2)

我将如何操作:首先,使用rexp的矢量化版本,如果您只想计算2的数字而不使用表格,请不要使用表格。{0}使用可以使用整数的字符。

rexp <- function(x, p) {
  x + (runif(length(x)) <= p)
}

replicate(500, {
  sum(rexp(obs, 0.03) == 2)
})

对于大小为880的输入:

microbenchmark::microbenchmark(
  ME = {
    replicate(500, {
      sum(rexp(obs, 0.03) == 2)
    })
  },
  OP = {
    for(i in 1:500){
      x <- sapply(obs,rexp,0.03)
      x <- table(x)
      x <- x[names(x) == 2]
      dat$result[i] <- x
    }
  },
  times = 10
)

Unit: milliseconds
 expr        min         lq       mean     median         uq        max neval
   ME   18.24666   18.31957   19.64568   20.05481   20.48095   21.69269    10
   OP 1362.54543 1395.50414 1426.17977 1414.25281 1439.75136 1542.97861    10