2017-09-27 236 views
3

我想優化此嵌套for循環,其中需要最少的2個數字,然後將結果添加到數據框。我可以通過矢量化和初始化大大減少它,但我不太確定如何將該邏輯應用於嵌套for循環。有沒有一種快速的方法來使這個運行更快?坐在超過5小時的運行時間。如何優化嵌套for循環R

「模擬」 具有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") 
+0

看看了'apply'家庭,我想'lapply'會工作在你的情況。它可以有效地替代'for'並且運行得更快(或者我發現並閱讀了其他人的發現)。另外,我們可以得到一個輸入(頭(模擬))和輸出(頭(限制))嗎?所以我們可以看到數據的結構?如果你是完全向量化的,「sapply」可能會完成這項工作(儘管如此,我並不擅長)。 – Badger

+0

您正在做5.42億次計算。你究竟會怎樣處理所得到的輸出矩陣呢? – thelatemail

+0

@thelatemail計算有限的方差/標準差。開發複雜的分佈,沒有好的公式來計算理論值,所以我們使用的是模擬 –

回答

1

如果您有> 15GB的RAM(〜100K * 5500 * 8個字節數* 3(結果+外X瓦爾斯+外Ÿ丘壑)),您可以嘗試:

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

雖然在現實中,你可能需要比15GB BEC更多因爲我認爲pmin會更多地複製東西。如果你沒有內存,你將不得不分解這個問題(例如,依靠一次編寫某列的代碼或某些代碼)。

1

基本上,當你有一個雙循環時,使用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] 

其中 '填寫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]); 
}