在初始值之后使用先前值对向量执行操作

osh*_*hun 6 r

在Excel中,通过引用较早的单元格,可以轻松地对先前单元格执行计算.例如,从初始值100(步骤= 0)开始,每个下一步将0.9 * previous + 9简单地通过从第一个单元格向下拖动公式栏(步骤= 1).接下来的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
Run Code Online (Sandbox Code Playgroud)

我环顾网络和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
Run Code Online (Sandbox Code Playgroud)

Wal*_*ltS 12

看起来你正在寻找一种在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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

对于这两个函数,输出的长度由输入向量的长度给出x.
这两种方法都可以提供结果.


Rol*_*and 9

使用我们关于几何系列的知识.

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
Run Code Online (Sandbox Code Playgroud)