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

时间:2012-05-06 01:17:12

标签: r loops for-loop

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

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

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

pv[1] <- 0
for(i in 2:length(x)) {
  pv[i] <- (x[i] - x[i-1])/x[i-1]
}

因此,正如您所看到的,我必须同时使用x[i]元素和x[i-1]元素。通过使用*apply函数,我只看到如何使用x[i]。无论如何我可以避免for循环吗?

3 个答案:

答案 0 :(得分:20)

您可以通过以下方式获得相同的结果:

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

曾经存在问题的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

enter image description here

答案 1 :(得分:18)

你提供的是分数变化,但是如果你乘以100就得到“变异百分比”:

pv<- vector("numeric",length(x))
pv[1] <- 0
pv[-1] <- 100* ( x[-1] - x[-length(x)] )/ x[-length(x)]

矢量化解决方案。 (你应该注意,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)]

答案 2 :(得分:16)

您还可以使用diff

c( 0, diff(x) / x[-length(x)] )
c( 0, exp(diff(log(x))) - 1 )