r - 避免R中的for循环

标签 r optimization vectorization

我想要一些关于编写更好的 R 代码的建议。我目前在 R 中编写了一个循环,但它存在性能问题。

我无法将其矢量化,因为输出数据帧中的每一行都依赖于较早的行,并且它们会迭代地向下传递,因此我编写了一个循环来按顺序读取/写入行。

我的代码示例:

example <- data.frame(a=c(.5,.1,.5,.25),b=c(1,0,2,0),c=c(1,2,3,4),d=c(4,3,2,1))

for (i in 2:nrow(example)) {
  if (example[i,1]>0) {
    example[i,2]<-example[i,2]+example[i-1,2]*example[i,1]
    example[i,3]<-example[i,3]+example[i-1,3]*example[i,1]
    example[i,4]<-example[i,4]+example[i-1,4]*example[i,1]

  }
}

看看发生了什么:
# before    
     a b c d
1 0.50 1 1 4
2 0.10 0 2 3
3 0.50 2 3 2
4 0.25 0 4 1

# after
     a      b      c     d
1 0.50 1.0000 1.0000 4.000
2 0.10 0.1000 2.1000 3.400
3 0.50 2.0500 4.0500 3.700
4 0.25 0.5125 5.0125 1.925

最佳答案

我不确定如何通过行操作来避免,但这里有 3 条建议可以通过 提高性能~X90

  • 使用矩阵代替 data.frames 进行此类操作
  • 预分配要操作的行
  • 循环内的矢量化操作

  • 换句话说,尝试将您的代码转换为
    indx <- which(example[-1, 1] > 0)
    for(i in indx + 1) example[i, -1] <- example[i, -1] + example[i-1, -1] * example[i, 1]
    

    另请注意,此解决方案适用于任意数量的列

    基准
    set.seed(123)
    N <- 1e3
    test <- matrix(runif(N * 4), ncol = 4)
    example <- as.data.frame(test)
    
    
    OP <- function(x){
      for (i in 2:nrow(x)) {
        if (x[i, 1]>0) {
          x[i,2]<-x[i,2]+x[i-1,2]*x[i,1]
          x[i,3]<-x[i,3]+x[i-1,3]*x[i,1]
          x[i,4]<-x[i,4]+x[i-1,4]*x[i,1]
        }
      }
      x
    }
    
    David <- function(x){
      indx <- which(x[-1, 1] > 0)
      for(i in indx + 1) x[i, -1] <- x[i, -1] + x[i-1, -1] * x[i, 1]
      x
    }
    
    identical(OP(example), as.data.frame(David(test)))
    # [1] TRUE
    
    library(microbenchmark)    
    microbenchmark(OP(example), David(test))    
    # Unit: milliseconds
    #        expr        min         lq       mean     median         uq        max neval cld
    # OP(example) 243.913429 246.248061 257.672703 247.104350 256.701590 337.375850   100   b
    # David(test)   3.020688   3.080685   3.336778   3.133483   3.301797   9.240615   100  a 
    

    关于r - 避免R中的for循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38725801/

    相关文章:

    python - 在 python 中快速计算 XMX^T 对角线的方法

    performance - 在 Matlab 中学习加速和矢量化技巧的最佳资源

    r - 如何抓取 "-"之后的一些字符?

    r - 如何添加到 R 中的列

    r - 在 R 中使用线性插值添加缺失的 xts/zoo 数据

    mysql - 在 MySQL 中跨数百万行使用 VARCHAR 与 INT

    python - SciPy 最小化 : How do I print the value of the finite difference Jacobian?

    r - 确定变量何时从 R 中的正值连续减少到负值

    algorithm - 如何优化解决方案以获得线性性能以找到直方图的孔总面积?

    c++ - 如何使用这个宏来测试内存是否对齐?