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