14

我知道使用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循环吗?

4

3 回答 3

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 循环并不慢,甚至可能比 apply 解决方案更快。您必须同时测试它们并查看。我打赌你的 for 循环比我的解决方案更快。

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

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

在此处输入图像描述

于 2012-05-06T01:28:01.760 回答
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)]

于 2012-05-06T01:28:15.180 回答
16

您还可以使用diff

c( 0, diff(x) / x[-length(x)] )
c( 0, exp(diff(log(x))) - 1 )
于 2012-05-06T01:49:05.743 回答