【问题标题】:Improve perfomance of loop提高循环性能
【发布时间】:2020-08-25 02:52:58
【问题描述】:

我正在努力提高以下代码的性能,该代码运行了大约 200 万个条目。首先,条件在循环内,现在在循环外,这带来了一些改进,但还不够。

您还有其他想法吗?


if (Floor=="Yes") { 
  for (i in 1:length(X)){
     base_short_term[i] <- pmax(numeric_vector1[i],(1+numeric_vector2[i])^((numeric_vector3[i])/(1+numeric_vector4[i]))
  }
} else {
for (i in 1:length(X)){  
     base_short_term[i] <- pmin(numeric_vector5[i],(1+numeric_vector3[i])^((numeric_vector5[i])/(1+numeric_vector7[i]))
 }
}

【问题讨论】:

  • 请展示一个可重现的小例子

标签: r performance loops


【解决方案1】:
R 中的

循环很糟糕,应尽可能避免。情况就是这样:向量化操作会更有效率(循环会导致内存开销)和更易读的代码:

df <- data.frame(x1 = numeric_vector1,
                x2 = numeric_vector2,
                x3 = numeric_vector3,
                x4 = numeric_vector4,
                x5 = numeric_vector5,
                x7 = numeric_vector7)

if (Floor == "yes"){
   df$base_short_term <- pmax(df$x1, (1+df$x2)^(df$x3/df$x4))
} else{
   df$base_short_term  <- pmin(df$x5, (1+df$x3)^(df$x5/df$x7))
}

如果无法避免循环,最好使用lapply或支持Rcpp

更新

如果向量具有不同的长度,您将失去性能,因为您需要先从 1 切片到 length(X) 或使用 lapply

切片向量

df <- data.frame(x1 = numeric_vector1[seq_along(X)],
                x2 = numeric_vector2[seq_along(X)],
                x3 = numeric_vector3[seq_along(X)],
                x4 = numeric_vector4[seq_along(X)],
                x5 = numeric_vector5[seq_along(X)],
                x7 = numeric_vector7[seq_along(X)])

(此解决方案是可能的,因为即使向量的长度不同,您也只能对所有向量使用不超过 length(X) 的索引)

lapply

看起来确实像您的 for 循环,但效率更高,因为它避免了在每次迭代时创建和转储对象

例如,如果FloorTRUE

base_short_term <- lapply(seq_along(X), function(i), {
     pmax(numeric_vector1[i],(1+numeric_vector2[i])^((numeric_vector3[i])/(1+numeric_vector4[i]))
  })

【讨论】:

  • 非常感谢您的回答。在最初的例子中,length(X) 与数字向量的长度不同。如果数字向量的长度不同(一个与另一个),它会以某种方式影响响应?
  • 这里,由于您只使用最大为length(X) 的向量索引,您可以将它们切片并组合到一个数据帧中。如果您不想创建数据框,我提出了一个lapply 解决方案,它应该比for 更有效
猜你喜欢
  • 1970-01-01
  • 2013-01-29
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 2014-07-27
  • 2021-11-06
相关资源
最近更新 更多