【问题标题】:How to optimize nested for Loop R如何优化嵌套循环 R
【发布时间】:2018-03-09 12:50:46
【问题描述】:

我正在尝试优化这个嵌套的 for 循环,它取 2 个数字中的最小值,然后将结果添加到数据帧中。我能够使用矢量化和初始化显着减少它,但我不太确定如何将该逻辑应用于嵌套的 for 循环。有没有一种快速的方法可以让这个运行更快?运行时间超过 5 小时。

“模拟”有 100k 个值,“限制”有 5427 个值

output <- data.frame(matrix(nrow = nrow(simulation),ncol = nrow(limits)))
res <- character(nrow(simulation))

for(i in 1:nrow(limits)){
    for(j in 1:nrow(simulation)){
        res[j] <- min(limits[i,1],simulation[j,1])
    }
    output[,i] <- res
}

编辑*

dput(head(simulation))
    structure(list(simulation = c(124786.7479,269057.2118,80432.47896,119513.0161,660840.5843,190983.7893)), .Names = "simulation", row.names = c(NA,6L), class = "data.frame")

dput(head(limits))
    structure(list(limits = c(5000L,10000L,20000L,25000L,30000L)), .Names = "limits", row.names = c(NA, 6L), class = "data.frame")

【问题讨论】:

  • 看看apply 家庭,我认为lapply 适合您的情况。它可以有效地替代for 并且运行速度更快(或者我发现并阅读了其他人的发现)。另外,我们可以得到dput(head(simulation))dput(head(limits)) 吗?那么我们可以看到数据的结构吗?如果你完全矢量化sapply 可能会完成工作(不过我不太擅长)。
  • 您正在进行 5.42 亿次计算。你到底要如何处理生成的output 矩阵?
  • @thelatemail 计算有限方差/标准。 dev 用于复杂的分布,没有好的公式可以仅计算理论值,因此我们正在使用模拟

标签: r loops for-loop optimization nested


【解决方案1】:

如果您有 >15GB 的 RAM(~100K * 5500 * 每个数字 8 个字节 * 3(结果 + 外部 x vals + 外部 y vals)),您可以尝试:

outer(simulation[[1]], limits[[1]], pmin)

虽然实际上您可能需要超过 15GB 的空间,因为我认为 pmin 会复制更多内容。如果您没有 ram,则必须解决问题(例如,依赖一次执行一列的代码或类似的代码)。

【讨论】:

    【解决方案2】:

    基本上,当您有双循环时,使用 Rcpp 通常很有用。

    此外,我将使用包 bigstatsr 为您节省一些 RAM。您可以创建和访问存储在磁盘上的矩阵。

    所以,你可以这样做:

    simulation <- structure(list(simulation = c(124786.7479,269057.2118,80432.47896,119513.0161,660840.5843,190983.7893)), .Names = "simulation", row.names = c(NA,6L), class = "data.frame")
    limits <- structure(list(limits = c(5000L,10000L,15000L, 20000L,25000L,30000L)), .Names = "limits", row.names = c(NA, 6L), class = "data.frame")
    
    library(bigstatsr)
    # Create the filebacked matrix on disk (in `/tmp/` by default)
    mat <- FBM(nrow(simulation), nrow(limits))
    # Fill this matrix in Rcpp
    Rcpp::sourceCpp('fill-FBM.cpp')
    fillMat(mat, limits[[1]], simulation[[1]])  
    # Access the whole matrix in RAM to verify
    # or you could access only block of columns
    mat[]
    mat[, 1:3]
    

    'fill-FBM.cpp' 在哪里

    // [[Rcpp::depends(bigstatsr, BH)]]
    #include <bigstatsr/BMAcc.h>
    #include <Rcpp.h>
    using namespace Rcpp;
    
    
    // [[Rcpp::export]]
    void fillMat(Environment BM,
                 const NumericVector& limits,
                 const NumericVector& simulation) {
    
      XPtr<FBM> xpBM = BM["address"];
      BMAcc<double> macc(xpBM);
    
      int n = macc.nrow();
      int m = macc.ncol();
    
      for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
          macc(j, i) = std::min(limits[i], simulation[j]);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-06
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 2012-01-27
      相关资源
      最近更新 更多