R - 多个嵌套循环地狱

时间:2015-07-16 20:27:34

标签: r for-loop matrix

我想从3个向量创建一个矩阵列表,其中sd_vec是严格正的:

z_vec <- c(qnorm(0.90), qnorm(0.95), qnorm(0.975))  # 95% CI, 90% CI, 80% CI
me_vec <- c(0.50, 0.25, 0.10, 0.05)
sd_vec <- rnorm(n = 9, 0.8, 0.4)
sd_vec[which(sd_vec <= 0)] <- 0.1

我的问题是双重的:

  • 如何将我的循环从1个矩阵推广到多个矩阵?我可以逐步创建矩阵(2个嵌套级别),但是当我嵌套所有3个级别时,我的索引会崩溃。
  • 如何完全避免for循环(本着this answer的精神)?我欢迎使用sapply()等任何答案

以下是我的尝试示例:

new_n <- matrix(NA, 3,4)
for(i in seq_along(z_vec)){
  for(j in seq_along(me_vec)){
    new_n[i, j] <- ((z_vec[i] * sd_vec[1]) /me_vec[j])^2
  }
}

new_n
#      [,1]  [,2]  [,3] [,4]
# [1,] 2.45  9.82  61.4  245
# [2,] 4.04 16.17 101.1  404
# [3,] 5.74 22.96 143.5  574

然后我的索引失败:

new_n <- vector("list", length = length(sd_vec))
for(k in seq_along(sd_vec)){
  for(i in seq_along(z_vec)){
    for(j in seq_along(me_vec)){
      new_n[[k]][i, j] <- ((z_vec[i] * sd_vec[k]) /me_vec[j])^2
    }
  }
}

错误消息Error in new_n[[k]][i, j] <- ((z_vec[i] * sd_vec[k])/me_vec[j])^2 : incorrect number of subscripts on matrix

感谢您对这个微不足道的问题的任何和所有帮助!

2 个答案:

答案 0 :(得分:1)

关于上一个示例中的错误消息,我认为这是由于矩阵列表的初始化不正确。 您可以尝试替换

new_n <- vector("list", length = length(sd_vec))

new_n <- replicate(length(sd_vec), matrix(NA, 3, 4), simplify = FALSE)

这应解决索引错误问题。寻找一种优雅而紧凑的方法来重写复杂的嵌套循环是另一个问题。我相信SO社区很快就能找到很好的解决方案。

<强>更新

第一个示例中的嵌套循环可以像这样重写:

new_n <- t(sapply(seq_along(z_vec), function(x,y) ((z_vec[x] * sd_vec[1]) / me_vec[y])^2))

答案 1 :(得分:0)

如何创建矩阵列表here,并计算每个没有for循环的矩阵,我们可以使用&#39; outer&#39;:

z_vec <- c(qnorm(0.90), qnorm(0.95), qnorm(0.975))  # 95% CI, 90% CI, 80% CI
me_vec <- c(0.50, 0.25, 0.10, 0.05)
sd_vec <- rnorm(n = 9, 0.8, 0.4)
sd_vec[which(sd_vec <= 0)] <- 0.1

new_n <- list()

for ( k in seq_along(sd_vec) )
{
  new_n[[k]] <- outer( z_vec*sd_vec[k], me_vec,
                       FUN = function(x,y){ (x/y)^2 } )
}

使用&#39;外部&#39;两次,可以在没有任何for循环的情况下生成包含与&#39; new_n&#39;相同的矩阵的三维数组:

A <- outer( outer( sd_vec, z_vec, "*"),
            me_vec, function(x,y){ (x/y)^2 } )

然后&#39; new_n [[k]]&#39;与“A [k ,,]&#39;相同对于每个&#39;。 为了摆脱最后的'-loop,我们可以使用&#39; alply&#39;来自图书馆&#39; plyr&#39;转为三维array into a list of matrices

library(plyr)

z_vec <- c(qnorm(0.90), qnorm(0.95), qnorm(0.975))  # 95% CI, 90% CI, 80% CI
me_vec <- c(0.50, 0.25, 0.10, 0.05)
sd_vec <- rnorm(n = 9, 0.8, 0.4)
sd_vec[which(sd_vec <= 0)] <- 0.1

A <- outer( outer( sd_vec, z_vec, "*"),
            me_vec, function(x,y){ (x/y)^2 } )

new_n <- alply(A,1)