2015-09-25 58 views
1

我有一个数组数据=阵列[1:50,1:50,1:50]数组R是值内是-1之间的实数,1优化循环使用并行

“数据”能视为立方体50x50x50。

我需要创建基于此方程=>

值=(X + Y)的相关矩阵(除去全零) - | X-Y |并且矩阵大小是可能组合(50×50×50)×((50×50×50)-1)/ 2 = 7.812.437.500这2倍=相关矩阵的2倍。

我这样做:

比方说我们的3x3x3:

arr = array(rnorm(10), dim=c(3,3,3)) 

data = data.frame(array(arr)) 


data$voxel <- rownames(data) 

#remove zeros 
data<-data[!(data[,1]==0),] 

rownames(data) = data$voxel 

data$voxel = NULL 


####################################################################################### 
#Create cluster 

no_cores <- detectCores() #- 1 

clus <- makeCluster(no_cores) 

clusterExport(clus, list("data") , envir=environment()) 

clusterEvalQ(clus, 
      compare_strings <- function(j,i) { 
       value <- (data[i,]+data[j,])-abs(data[i,]- data[j,]) 
       pair <- rbind(rownames(data)[j],rownames(data)[i],value) 
       return(pair) 
      }) 

i = 0 # start 0 
kk = 1 
table <- data.frame() 

ptm <- proc.time() 

while(kk<nrow(data)) { 

    out <-NULL 
    i = i+1 # fix row 
    j = c((kk+1):nrow(data)) # rows to be compared 

    #Apply the declared function 
    out = matrix(unlist(parRapply(clus,expand.grid(i,j), function(x,y) compare_strings(x[1],x[2]))),ncol=3, byrow = T) 

    table <- rbind(table,out) 

    kk = kk +1 

} 

proc.time() - ptm 

结果是data.frame:

v1 v2 v3 
1 2 2.70430114250358 
1 3 0.199941717684129 
... up to 351 rows 

但是这将需要数天...

另外,我想创建一个这种关联矩阵:

1       2    3... 
1 1     2.70430114250358 
2 2.70430114250358   1 
3... 

有没有更快的方法来做到这一点?

感谢

+3

请给我们一个小[再现的示例](http://stackoverflow.com/a/5963610/1412059)(例如,用3x3x3的阵列)与和显示工作预期的产出。如果无法找到矢量化解决方案(可疑),则应使用Rcpp执行此操作(即,在编译代码中执行循环)。 – Roland

+0

由于无法找到“S”,因此您当前生成'data'的代码无法运行。 – Heroka

+0

大家好,我已经编辑了一些更多解释的帖子。谢谢 – DemetriusRPaula

回答

0

有一些在你的代码性能的错误:

  1. 你循环时,你应该依靠量化。
  2. 你在循环中生长一个对象。
  3. 您可以并行化循环的每个迭代而不是并行化外循环。

如果避免第一个问题,可以避免所有这些问题。

显然,你想要比较每个行的组合。对于这一点,你应该先把排索引的所有组合:

combs <- t(combn(1:27, 2)) 

那么你可以申请比较函数这些:

compare <- function(j,i, data) { 
    as.vector((data[i,]+data[j,])-abs(data[i,]- data[j,])) 
} 

res <- data.frame(V1 = combs[,1], V2 = combs[,2], 
        V3 = compare(combs[,1], combs[,2], data)) 

现在,如果我们要检查,如果这给出结果为相同你的代码,我们首先需要修复你的输出。通过将字符(rownames)与矩阵中的数字相结合,可以得到一个字符矩阵,并且最终data.frame的列都是字符。我们可以用type.convert来修复之后(尽管它应该从一开始就避免):

table[] <- lapply(table, function(x) type.convert(as.character(x))) 

现在我们看到的结果是一样的:

all.equal(res, table) 
#[1] TRUE 

如果你喜欢,你可以把结果为稀疏矩阵:

library(Matrix) 
m <- sparseMatrix(i = res$V1, j = res$V2, x = res$V3, 
        dims = c(27, 27), symmetric = TRUE) 
diag(m) <- 1 
+0

combs <-t(combn(1:83346,2))不适用于大小:( – DemetriusRPaula

+0

)那么这就是'3,473,236,185'组合。我相信你应该重新考虑你想要做的事情,但是如果你坚持要做到这一点,你可以使用Rcpp。当然,你需要一个大的RAM,或者将Rcpp与其中一个包装用于内存不足的数据结合。 – Roland

+0

cppFunction('Rcpp :: DataFrame combi2inds(const Rcpp :: CharacterVector inputVector)const int len = inputVector.size(); const int retLen = len *(len-1)/ 2; Rcpp :: IntegerVector outputVector1(retLen); Rcpp :: IntegerVector outputVector2(retLen); int indexSkip; for(int i = 0; i DemetriusRPaula