R中的循环 - 需要使用索引,无论如何要避免'for'?

Joã*_*iel 14 loops for-loop r

我知道在R中使用for循环并不是最好的做法,因为它没有增强的性能.对于几乎所有情况,家庭都有*apply解决我们问题的功能.

但是我面临着一种我没有看到解决方法的情况.

我需要计算连续值的百分比变化:

pv[1] <- 0
for(i in 2:length(x)) {
  pv[i] <- (x[i] - x[i-1])/x[i-1]
}
Run Code Online (Sandbox Code Playgroud)

所以,正如你所看到的,我必须既使用x[i]元素,也使用x[i-1]元素.通过使用这些*apply功能,我只看到如何使用x[i].无论如何,我可以避免for循环?

Tyl*_*ker 20

你可以得到相同的结果:

pv <- c(0)
y <- sapply(2:length(x), function(i) {pv <<- (x[i] - x[i-1])/x[i-1]})
c(0, y)
Run Code Online (Sandbox Code Playgroud)

曾经是问题的for循环问题已得到优化.for循环通常不会慢,甚至可能比应用解决方案更快.你必须测试它们并看到.我打赌你的for循环比我的解决方案更快.

编辑:只是为了说明for循环与应用解决方案以及DWin讨论的关于矢量化的内容,我在win 7机器上使用microbenchmark对四种解决方案进行了基准测试.

Unit: microseconds
             expr     min      lq  median      uq       max
1    DIFF_Vincent  22.396  25.195  27.061  29.860  2073.848
2        FOR.LOOP 132.037 137.168 139.968 144.634 56696.989
3          SAPPLY 146.033 152.099 155.365 162.363  2321.590
4 VECTORIZED_Dwin  18.196  20.063  21.463  23.328   536.075
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


42-*_*42- 18

您提供的是分数变化,但如果乘以100,则得到"百分比变化":

pv<- vector("numeric",length(x))
pv[1] <- 0
pv[-1] <- 100* ( x[-1] - x[-length(x)] )/ x[-length(x)]
Run Code Online (Sandbox Code Playgroud)

矢量化的解决方案 (你应该注意,for循环和*apply解决方案一样慢......只是不那么漂亮.总是寻找一种矢量化的方法.)

为了解释一下:它x[-length(x)]是向量,x[1:(length{x-1)]并且x[-1]是向量,x[2:length(x)]并且R中的向量运算正在执行与for循环体相同的操作,尽管不使用显式循环.R首先构造那些移位向量的差异x[-length(x)] - x[-1],然后除以x[1:(length{x-1)].


Vin*_*ynd 16

您还可以使用diff:

c( 0, diff(x) / x[-length(x)] )
c( 0, exp(diff(log(x))) - 1 )
Run Code Online (Sandbox Code Playgroud)