【问题标题】:optimization of iterative calculation avoiding loops on R优化迭代计算,避免 R 上的循环
【发布时间】:2017-06-04 14:11:16
【问题描述】:

我必须对 R 中的 data.frame 行应用迭代计算。 问题是,对于每一行,结果取决于之前的计算结果和之前的行。

我已经使用类似以下示例的循环实现了解决方案:

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]
}

问题是真正的代码很慢(特别是如果我在 KNIME 上的 R sn-p 中使用它)

有没有办法以更高效的类似 R 的方式优化代码?我尝试使用 apply 系列,但在我的情况下似乎不起作用。

非常感谢

【问题讨论】:

    标签: r loops optimization iteration knime


    【解决方案1】:

    这是使用累积的flag_new 进行分组的data.table 努力

    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)
    

    通过对从第一个 TRUE 到下一个要完成的计算进行分组 计算可以在没有循环的情况下完成。

    例如,使用第一组计算可以完成为

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

    这来自 as

    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..
    

    所以只需要一个 split、apply、combine 方法来为每个组计算这些 我使用了data.table

    【讨论】:

    • 非常感谢@user20650。它确实有助于解决我的大部分问题。这个例子是一个更大问题的简化。如果我有这样的东西怎么办:'example$K[i]
    • 我认为这将取决于函数 f 和 g 是什么。你能用一个小例子来编辑你的问题吗,包括函数,它可以重现你的实际问题(用代码来显示预期的结果,和以前一样)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 2013-05-29
    • 2023-02-08
    • 2015-07-19
    • 2019-11-17
    • 1970-01-01
    • 2018-12-05
    相关资源
    最近更新 更多