2016-02-29 27 views
4

在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 

我的網站和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 
+2

請勿使用'append'。將'value'預分配給最終大小並分配給它的元素。增長一個對象是你能做的最慢的操作之一。 – Roland

回答

10

好像你正在尋找一個方式做遞歸計算在R.基礎R具有這樣它通過用做遞歸函數的形式不同的兩種方式。這兩種方法都可以用於你的例子。

Reduce可以與形式爲v[i+1] = function(v[i], x[i])的遞歸方程式一起使用,其中v是計算的向量並且x是輸入向量;即其中輸出只取決於計算和輸入矢量的第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輸入矢量的遞歸方程;即輸出可以線性地依賴於所計算的矢量的滯後值以及輸入矢量的值。對於你的情況下,這將是:

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的長度給出。
這兩種方法都會給出結果。

8

使用關於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 
+0

很棒的回答(+1)@Roland!我選擇了@ WaltS的答案,因爲它比較靈活,比如常量本身就是變量。 – oshun

相關問題