0

我需要使用两个相同大小的迭代变量(例如1:n )执行foreach,但函数会并行更改它们,如下所示

我们称 a 和 b 为迭代变量,因为它们是在多次执行期间不断变化的变量。请注意,我们正在并行迭代它们,也就是说,它们都在同时发生变化。

我需要的是让 foreach 独立更改它们,这样我就有一个长度为n^2的列表,而不是n

例子:

X = foreach(i=1:n, j=1:n) %do% (sum(M[i,]*M[j,]))

最后我得到一个长度为n的向量,它只是矩阵 X 的对角线,而不是完整的矩阵。

PS我试图用for循环来做这个,但是计算时间太长了,不能让代码未经优化。

4

2 回答 2

1

要嵌套foreach循环,请使用嵌套运算符“%:%”:

library(foreach)
n <- 4
M <- matrix(rnorm(n*n), n)
X <- foreach(i=1:n, .combine='cbind') %:%
       foreach(j=1:n, .combine='c') %do% {
         sum(M[i,]*M[j,])
       }

为避免重复计算,您可以从toj迭代,并使用函数来填充结果向量:in.finalNA

pad <- function(x) c(rep(NA, n - length(x)), x)
Y <- foreach(i=1:n, .combine='cbind') %:%
       foreach(j=i:n, .combine='c', .final=pad) %do% {
         sum(M[i,]*M[j,])
       }

但这些解决方案仅具有学术意义。为了简单和速度,我怀疑这tcrossprod是迄今为止最好的解决方案:

Z <- tcrossprod(M)

对于 4000 X 4000 矩阵,这在我的 Linux 机器上执行不到 8 秒。

于 2013-08-07T18:18:24.043 回答
1

foreach并不比 更有效for。查找%:%@BenBarnes 评论的运算符以使用它。并行化可能会有所帮助,但作用不大。

尝试以下而不是显式循环:

M <- matrix(1:8,4)

prodsums <- combn(seq_len(nrow(M)), 2, FUN=function(ind) {
  res <- sum(M[ind[1],]*M[ind[2],])
  names(res) <- paste(ind, collapse="*")
  res
}, simplify=F)

unlist(prodsums)
#1*2 1*3 1*4 2*3 2*4 3*4 
# 32  38  44  48  56  68 

resmat <- matrix(ncol=nrow(M),nrow=nrow(M))
resmat[lower.tri(resmat)] <- unlist(prodsums)
#       [,1] [,2] [,3] [,4]
# [1,]   NA   NA   NA   NA
# [2,]   32   NA   NA   NA
# [3,]   38   48   NA   NA
# [4,]   44   56   68   NA

resmat[upper.tri(resmat)] <- t(resmat)[upper.tri(resmat)]

diag(resmat) <- rowSums(M^2)
#     [,1] [,2] [,3] [,4]
#[1,]   26   32   38   44
#[2,]   32   40   48   56
#[3,]   38   48   58   68
#[4,]   44   56   68   80
于 2013-08-06T13:09:31.103 回答