2016-02-09 96 views
0

我正在運行此for loop沒有任何問題,但它需要很長時間。我想應用家庭可以更快,但不知道如何。任何提示?索引需要很長時間for循環?

set.seed(1) 
nrows <- 1200 
ncols <- 1000 
outmat <- matrix(NA, nrows, ncols) 
dat <- matrix(5, nrows, ncols) 
for (nc in 1 : ncols){ 
    for(nr in 1 : nrows){ 
    val <- dat[nr, nc] 
    if(!is.na(val)){ 
     file <- readBin(dir2[val], numeric(), size = 4, n = 1200*1000) 
     # my real data where dir2 is a list of files 
     # "dir2 <- list.files("/data/dir2", "*.dat", full.names = TRUE)" 
     file <- matrix((data = file), ncol = 1000, nrow = 1200) #my real data 

     outmat[nr, nc] <- file[nr, nc] 
    } 

    } 
} 
+5

請你可以描述一下你的數據。它不清楚爲什麼你不把所有的1200 x 1000作爲一個單塊讀入內存。你有多少塊?我不使用bin文件(傾向於使用帶'read.table'或'fread'的csv文件),因此可能會忽略這一點。 – micstr

+0

我不確定您是否擁有1200000個不同的文件,但是您的循環需要這麼久,因爲您實際上正在讀取1200000個文件,而且如果速度非常慢,則會進行磁盤訪問。申請不會更快。如果你沒有這麼多的文件,我會建議恢復你的進程,先讀取每個文件並存儲它的數據,然後根據需要循環處理數據。 – HubertL

+0

'dir2'中有多少個文件? – nicola

回答

3

兩種解決方案。

第一次填充的內存更多,但效率更高,如果您有24個文件,我認爲可行。您一次讀取所有文件,然後根據dat正確地設置子集。例如:

allContents<-do.call(cbind,lapply(dir2,readBin,n=nrows*ncol,size=4,"numeric") 
res<-matrix(allContents[cbind(1:length(dat),c(dat+1))],nrows,ncols) 

第二個可以處理稍大一些的文件(比如50-100)。它讀取每個文件和子集的塊。您必須打開與獲得的文件數量一樣多的連接。例如:

outmat <- matrix(NA, nrows, ncols) 
connections<-lapply(dir2,file,open="rb") 
for (i in 1:ncols) { 
    values<-vapply(connections,readBin,what="numeric",n=nr,size=4,numeric(nr)) 
    outmat[,i]<-values[cbind(seq_len(nrows),dat[,i]+1)] 
} 

+1dat之後是由於這樣的事實,當你在評論中指出,從0〜23,R索引dat範圍的值是基於1的。