【问题标题】:Performance of for-loop with high number of cases具有大量案例的for循环的性能
【发布时间】:2018-09-04 11:34:03
【问题描述】:

我有 88.000 个观察值,用 1 编码:

obs <- rep(1,88000)

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

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

除了“obs”和“rexp”之外,还给出了一个空数据框“dat”,其中包含 500 行和 0 列。还有一个占位符“结果”:

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

我使用以下循环将函数“rexp”(p = 0.03)应用于向量“obs”500次,并将随机实验引起的“obs”变化次数保存为数据框中的“结果” “数据”:

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 次观察)。我知道无论如何都应该在 r 中绕过 for 循环,但我不知道如何执行该过程。我将不胜感激任何提示来解释和改进所描述的循环的性能!

【问题讨论】:

  • 第一步是将sapply(循环)替换为rexp的矢量化版本,即rexp &lt;- function(x, p) {ifelse(runif(length(x)) &lt;= p, x + 1, x)}dat 也可以初始化为整数的命名向量。

标签: r performance loops for-loop random


【解决方案1】:

我会怎么做:首先,使用rexp 的矢量化版本,然后如果您只想计算2 的数量并且不要使用可以使用整数的字符,请不要使用表格。

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

【讨论】:

    猜你喜欢
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    相关资源
    最近更新 更多