【问题标题】:Suggestions on speeding up my 5 loops in R?关于加快我在 R 中的 5 个循环的建议?
【发布时间】:2016-12-13 14:14:01
【问题描述】:

我有 5 张桌子,我想找到一些满足某些要求的组合。我可以通过使用矩阵乘法创建所有可能的组合,然后选择满足我需要的行来轻松解决以下数据。问题是我最初的问题由 5 个表组成,每个表有 200 行。如果生成所有可能的组合,这需要几百 GB 的内存。

所以我尝试了这个:

x1 <- seq(1,10,1)
x2 <- seq(5,15,3)
x3 <- seq(2,11,1)
x4 <- seq(1,5,1)
x5 <- seq(1,20,2)

应该满足:x1

nm <- data.frame(matrix(NA,1,5))

for(a in 1:length(x1)){
for(s in 1:length(x2)){
for(d in 1:length(x3)){
for(f in 1:length(x4)){
for(g in 1:length(x5)){

l1 <- x1[a]
l2 <- x2[s]

if(l1 < l2){

l3 <- x3[d]

if(l1 < l3){

l4 <- x4[f]
l5 <- x5[g]

fy <- c()
fy[1] <- l1
fy[2] <- l2
fy[3] <- l3
fy[4] <- l4
fy[5] <- l5

nm <- rbind(nm, fy)
}}}}}}}

在我原来的问题中,我有更多的 if 语句,我希望这会提高速度。但是我现在已经运行了大约 24 小时,但仍然没有完成。上面的问题花了我大约 10 秒,这让我觉得它卡住了。

【问题讨论】:

  • R 经验法则:尽可能使用矢量化操作而不是循环。
  • 为什么不用文字描述你想要做的事情,而不是向我们展示你是如何做到的。可能有更好的方法。或者可能没有。您是否计算过真实数据需要多少次迭代?
  • 我又添加了一行,但没有看到缺少什么来理解文字中的问题。我的原始数据大概有200^5个组合,不知道有多少符合要求。

标签: r performance loops


【解决方案1】:

两个问题:

最大的问题是你在循环中增长一个对象。这是可能的最慢操作,因为涉及巨大的操作系统开销。您需要预先分配对象,并且只在必要时以块的形式增长它。

中等问题是您使用 data.frame 来存储结果。 Data.frames 很有用,但速度很慢。请改用矩阵。

nm1 <- matrix(nrow = 1e3, ncol = 5) #adjust the chunk size to a reasonable estimate
rx <- 1

for(a in 1:length(x1)){
  for(s in 1:length(x2)){
    for(d in 1:length(x3)){
      for(f in 1:length(x4)){
        for(g in 1:length(x5)){

          l1 <- x1[a]
          l2 <- x2[s]

          if(l1 < l2){

            l3 <- x3[d]

            if(l1 < l3){

              l4 <- x4[f]
              l5 <- x5[g]

              if(rx > nrow(nm1)) nm1 <- rbind(nm1, matrix(nrow = 1e3, ncol = 5))

              nm1[rx, 1] <- l1
              nm1[rx, 2] <- l2
              nm1[rx, 3] <- l3
              nm1[rx, 4] <- l4
              nm1[rx, 5] <- l5

              rx <- rx + 1

            }}}}}}}

nm1 <- nm1[seq_len(rx - 1),]

时间安排:

Unit: milliseconds
       expr       min        lq      mean    median        uq       max neval cld
      mod()  589.2437  591.1576  594.4138  593.3678  595.0909  603.2087     5  a 
 original() 4934.4981 4952.4502 4980.6414 4953.3183 4985.7943 5077.1463     5   b

我们在没有真正开始考虑算法的情况下获得了 10 倍的性能提升。如果你有更多的迭代来增长 data.frame,这个因素会变得更大。如果这仍然太慢,您可以尝试使用编译器包对代码进行字节编译。使用 Rcpp 实现为实际编译的代码也很简单。但是,您应该通过增加迭代次数来进行基准测试,并将时间推断到您的实际问题。您可能需要找到比蛮力更好的算法,或者考虑是否真的需要这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    相关资源
    最近更新 更多