2011-07-08 51 views
1

下面是我正在處理的一段代碼的簡化版本(爲避免混淆,省略了大量附加計算)。這只是cumsum函數的修改形式。我不想重新發明輪子,這個功能是否已經存在?如果不是,什麼方案會提供最好的速度?修改後的cumsum函數

#Set up the data 
set.seed(1) 
junk <- rnorm(1000000) 
junk1 <- rnorm(1000000) 
cumval <- numeric(1000000) 

#Initialize the accumulator 
cumval[1] <- 1 

#Perform the modified cumsum 
system.time({ 
for (i in 2:1000000) cumval[i] <- junk[i] + (junk1[i] * cumval[i-1])  
}) 

#Plot the result 
plot(cumval, type="l")  
+0

會你介意多解釋一下這是如何使用的?請注意''junk [1]'和'junk1 [1]'從未用於您的算法中...... – Tommy

回答

1

這個算法是完全適合compiler包的東西!

#Set up the data 
set.seed(1) 
junk <- rnorm(1000000) 
junk1 <- rnorm(1000000) 

# The original code 
f <- function(junk, junk1) { 
    cumval <- numeric(1000000) 
    cumval[1] <- 1 
    for (i in 2:1000000) cumval[i] <- junk[i] + (junk1[i] * cumval[i-1]) 
    cumval 
} 
system.time(f(junk, junk1)) # 4.11 secs 

# Now try compiling it... 
library(compiler) 
g <- cmpfun(f) 
system.time(g(junk, junk1)) # 0.98 secs 

...所以這將是有趣的知道,如果該算法以任何方式「典型」 - 在這種情況下,編譯器或許可以更對這樣的情況下優化...

1

它更快,但不會給出正確的結果。 運行此

set.seed(1) 

N <- 10 

junk <- rnorm(N) 

junk1 <- rnorm(N) 

cumval <- numeric(N) 
cumval.1 <- numeric(N) 
cumval[1] <- 1 

for(i in 2:N) cumval[i] <- junk[i] + junk1[i]*cumval[i-1] 
cumval 

cumval.1 <- cumsum(junk[-1] + (junk1[-1] * cumval.1[-N])) 

cumval.1 

,你會看到cumval和cumval.1甚至沒有相同的長度。

需要重寫遞歸關係。 我沒有看到將重現轉換爲非重複公式的方法。

+0

這似乎不是答案,而是由@Seth對答案的評論。但是,你的觀點似乎是正確的。 – Andrie

1

考慮cumval [5]。使用j個[]用於垃圾和JK []爲junk1並省略*的符號,它的膨脹會是:

j[5] +jk[5]j[4] + jk[5]jk[4]j[3] + jk[5]jk[4]jk[3]j[2] + jk[5]jk[4]jk[3]jk[2]

的圖案表明,這可能是對第五項的表達式(接近):

sum( j[1:5] * c(1, Reduce("*" , rev(jk[2:5]), accumulate=TRUE)) 
+0

這是另一個版本的「cumsum」(通知Gabor G的回覆),涉及「Reduce」。 http://r.789695.n4.nabble.com/Cumsum-with-a-max-and-min-value-td3059498.html我還沒有弄清楚爲什麼這些工作還沒有完成,但是對於你的解決方案,有些東西可能會凝聚。 –