2017-01-19 92 views
2

我必須對R中的data.frame的行應用迭代計算。 問題是,對於每一行,結果取決於先前計算的結果和前一行。優化迭代計算避免循環R

我已經實現使用如以下示例所示的循環溶液:

example <- data.frame(flag_new = c(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE), 
         percentage =sample(1:100,22)/100) 
n.Row <- nrow(example) 

# initialization 
example$K <-0 
example$R <-0 
example$K[1] <-100 
example$R[1] <-example$K[1]*example$percentage[1] 

#loop 
for(i in 2:n.Row){ 
    if(example$flag_new[i]){ 
    example$K[i] <-100 

    } else { 
    example$K[i] <-example$K[i-1]-example$R[i-1] 
    } 
    example$R[i] <- example$K[i]*example$percentage[i] 
} 

的問題是,實際的代碼非常緩慢(expecially如果我用它作爲R代碼段上KNIME)

有沒有什麼辦法以更高效的R-like方式優化代碼?我試圖使用申請家庭,但它似乎不適用於我的情況。

非常感謝您

回答

1

這裏是你的問題在運行循環後data.table努力用累積flag_new到組

set.seed(1) 
example <- data.frame(flag_new = c(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE), 
         percentage =sample(1:100,22)/100)  

# initialization 
initK = 100 

# Copy to allow comparison to your code 
newd = example 

library(data.table) 
setDT(newd)[, Knew:= initK* c(1, cumprod(1 - percentage[-.N])), 
           by=cumsum(flag_new)][, Rnew:=Knew* percentage] 

比較的結果

all.equal(example$K, newd$Knew) 
all.equal(example$R, newd$Rnew) 

通過對fi進行的計算進行分組rst TRUE直到下一個 計算可以在沒有循環的情況下完成。

例如,使用第一組的計算可以做到

d = example[1:8, ] 
d$K1 <- d$K* c(1, cumprod(1 - d$percentage[-length(d$percentage)])) 
d$R2 <- with(d, K1* percentage) 

這來自作爲

k[i] = k[i-1] - R[i-1] 
k[i] = k[i-1] - k[i-1]* p[i-1] 
    = k[i-1](1 - p[i-1]) 
So 
k[2] = k[1]* (1-p[1]) 
k[3] = k[2]* (1-p[2]) = k[1]* (1-p[1])* (1-p[2]) 
k[4] = k[3]* (1-p[3]) = k[1]* (1-p[1])* (1-p[2])* (1-p[3]) 
and so on.. 

所以只需要一個分裂,應用相結合的方法,來計算這些對我使用的每個組 data.table

+0

非常感謝@ user20650。 這對我的問題有很大幫助。這個例子是一個更大問題的證明。如果我有這樣的事情:'舉例$ K [i] <-f(示例$ K [i-1],示例$ R [i-1])''和'示例$ R [i] < - g(示例$ K [i],示例$ percentage [i])' –

+0

我認爲這取決於f和g的功能。你可以用一個小例子來編輯你的問題,包括函數,它可以重現你的實際問題(用代碼來展示預期的結果,和以前一樣) – user20650