在Excel中,通过引用较早的单元格,可以轻松地对先前单元格执行计算。例如,从初始值100(步骤= 0)开始,仅通过从第一个单元格向下拖动公式栏(步骤= 1),每个下一步将是0.9 * previous + 9
。接下来的10个步骤如下:
step value
[1,] 0 100.00000
[2,] 1 99.00000
[3,] 2 98.10000
[4,] 3 97.29000
[5,] 4 96.56100
[6,] 5 95.90490
[7,] 6 95.31441
[8,] 7 94.78297
[9,] 8 94.30467
[10,] 9 93.87420
[11,] 10 93.48678
我已经浏览了网络和StackOverflow,我能想到的最好的是for
循环(下方)。有更有效的方法吗?是否可以避免for
循环?看起来R中的大多数函数(例如cumsum
,diff
,apply
等)都可以处理现有向量,而不是从以前的向量中动态计算新值。
#for loop. This works
value <- 100 #Initial value
for(i in 2:11) {
current <- 0.9 * value[i-1] + 9
value <- append(value, current)
}
cbind(step = 0:10, value) #Prints the example output shown above
答案 0 :(得分:11)
看起来你正在寻找一种在R中进行递归计算的方法.Base R有两种方法可以做到这一点,这种方式因用于递归的函数的形式而不同。这两种方法都可以用于您的示例。
Reduce
可以与v[i+1] = function(v[i], x[i])
形式的递归方程一起使用,其中v
是计算向量,x
是输入向量;即,i+1
输出仅取决于计算和输入矢量的第i个值,而function(v, x)
执行的计算可能是非线性的。对于你的情况,这将是
value <- 100
nout <- 10
# v[i+1] = function(v[i], x[i])
v <- Reduce(function(v, x) .9*v + 9, x=numeric(nout), init=value, accumulate=TRUE)
cbind(step = 0:nout, v)
filter
与y[i+1] = x[i] + filter[1]*y[i-1] + ... + filter[p]*y[i-p]
形式的递归方程一起使用,其中y
是计算向量,x
是输入向量;即,输出可以线性地取决于计算矢量的滞后值以及输入矢量的i-th
值。对于您的情况,这将是:
value <- 100
nout <- 10
# y[i+1] = x[i] + filter[1]*y[i-1] + ... + filter[p]*y[i-p]
y <- c(value, stats::filter(x=rep(9, nout), filter=.9, method="recursive", sides=1, init=value))
cbind(step = 0:nout, y)
对于这两个函数,输出的长度由输入向量x
的长度给出
这两种方法都可以为您提供结果。
答案 1 :(得分:9)
使用我们对geometric series的了解。
i <- 0:10
0.9 ^ i * 100 + 9 * (0.9 ^ i - 1) / (0.9 - 1)
#[1] 100.00000 99.00000 98.10000 97.29000 96.56100 95.90490 95.31441 94.78297 94.30467 93.87420 93.48678
答案 2 :(得分:0)
您也可以使用 purrr::accumulate
:
data.frame(value = purrr::accumulate(0:10, ~ .x * .9 + 9, .init = 100))
value
1 100.00000
2 99.00000
3 98.10000
4 97.29000
5 96.56100
6 95.90490
7 95.31441
8 94.78297
9 94.30467
10 93.87420
11 93.48678
12 93.13811
.init
是初始值,如果你想控制方向,还有参数 .dir
(“forward”是默认值)