避免R中的for循环 [英] Avoiding for loop in R

查看:95
本文介绍了避免R中的for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一些有关编写更好的R代码的建议.我目前已经在R中编写了一个循环,它遇到了性能问题.

I'd like some advice on writing better R code. I have currently written a loop in R and it suffers from performance issues.

我不能全力以赴地对它进行矢量化处理,因为输出数据帧中的每一行都依赖于较早的行,并且它们会逐滴递减,因此我编写了一个循环以按顺序读取/写入行.

I can't wrap my head around vectorizing it, because each row in the output data frame has dependencies upon earlier rows and they trickle down iteratively, so I have written a loop to read/write the rows in sequence.

我的代码示例:

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 的性能

I'm not sure how to avoid by row operations, but here are 3 advises that will improve performance by ~X90

  1. 使用矩阵而不是data.frames进行此类操作
  2. 预分配要操作的行
  3. 向量化循环中的操作

换句话说,尝试将您的代码转换为

In other words, try converting your code to

indx <- which(example[-1, 1] > 0)
for(i in indx + 1) example[i, -1] <- example[i, -1] + example[i-1, -1] * example[i, 1]

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

Also, note that this solution is generalized for any number of columns

基准

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中的for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆