2017-01-19 13 views
2

Мне нужно применить итеративный расчет по строкам data.frame в R. Проблема в том, что для каждой строки результат зависит от результатов предыдущего вычисления и предыдущих строк ,оптимизация итеративного вычисления, избегающего циклов на 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-стиле? Я попытался использовать семейство приложений, но, похоже, это не работает в моем случае.

Большое спасибо

ответ

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

спасибо @ пользователь20650. Это помогает в значительной части моей проблемы. В качестве примера можно привести более сложную проблему. Что делать, если у меня есть что-то вроде этого: «пример $ K [i] <-f (пример $ K [i-1], пример $ R [i-1]) 'и' пример $ R [i] <- g (пример $ K [i], пример $ percent [i]) ' –

+0

Я думаю, что это будет зависеть от того, что стоят функции f и g. Вы можете отредактировать свой вопрос с помощью небольшого примера, включая функции, которые воспроизводят вашу актуальную проблему (с кодом, чтобы показать ожидаемый результат, как и раньше) – user20650