我有一个包含大约25000条记录和10列的数据框。我正在使用代码来确定基于另一列(y)的同一列(NewVal)中前一个值的更改,其中已经有一个百分比变化。
x=c(1:25000)
y=rpois(25000,2)
z=data.frame(x,y)
z[1,'NewVal']=z[1,'x']
所以我跑了这个:
for(i in 2:nrow(z)){z$NewVal[i]=z$NewVal[i-1]+(z$NewVal[i-1]*(z$y[i]/100))}
这比我预期的要长得多。我可能是一个不耐烦的人 - 正如我曾经说过的一封严厉的信件 - 但我试图逃避Excel的世界(在我阅读http://www.burns-stat.com/pages/Tutor/spreadsheet_addiction.html之后,由于我开始不信任而导致我出现更多问题数据 - 那封信还提到了我的信任问题。)
我想在不使用包中的任何功能的情况下这样做,因为我想知道创建值的公式是什么 - 或者如果你愿意的话,根据那个友好的信息,我是一个要求极高的控制狂。
我也想知道如何像caTools中的rollmean一样获得移动平均线。要么是这样,要么我怎么弄清楚他们的公式是什么?我尝试进入rollmean,我认为它指的是另一个功能(我是R的新手)。这应该是另一个问题 - 但正如那封信所说的那样,我一生都没有做出正确的决定。
答案 0 :(得分:7)
R中的秘密是矢量化。在您的示例中,您可以使用cumprod
来完成繁重的工作:
z$NewVal2 <- x[1] * cumprod(with(z, 1 +(c(0, y[-1]/100))))
all.equal(z$NewVal, z$NewVal2)
[1] TRUE
head(z, 10)
x y NewVal NewVal2
1 25 4 25.00000 25.00000
2 24 3 25.75000 25.75000
3 23 0 25.75000 25.75000
4 22 1 26.00750 26.00750
5 21 3 26.78773 26.78773
6 20 2 27.32348 27.32348
7 19 2 27.86995 27.86995
8 18 3 28.70605 28.70605
9 17 4 29.85429 29.85429
10 16 2 30.45138 30.45138
在我的机器上,循环运行只需不到3分钟,而cumprod
语句几乎是瞬间完成的。
答案 1 :(得分:6)
我使用Reduce
提高了800倍:
system.time(z[, "NewVal"] <-Reduce("*", c(1, 1+z$y[-1]/100), accumulate=T) )
user system elapsed
0.139 0.008 0.148
> head(z)
x y NewVal
1 1 1 1.000
2 2 1 1.010
3 3 1 1.020
4 4 5 1.071
5 5 1 1.082
6 6 2 1.103
7 7 2 1.126
8 8 3 1.159
9 9 0 1.159
10 10 1 1.171
> system.time(for(i in 2:nrow(z)){z$NewVal[i]=z$NewVal[i-1]+
(z$NewVal[i-1]*(z$y[i]/100))})
user system elapsed
37.29 106.38 143.16