首页 > 解决方案 > 用向量替换三角矩阵的一部分

问题描述

我有v<- c(2,4,5)mat<- matrix(0,n,n)。我想替换矩阵上部的向量,我识别的每个地方,数组都替换为向量的长度数。例如,对于 n=5,输出可以是:

       [,1] [,2] [,3] [,4] [,5]
[1,]    0    2    4    0    0
[2,]    0    0    5    0    0
[3,]    0    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0

我尝试使用此代码:

mat <- matrix(0, nrow = 5, ncol = 5)
for (i in 1:5){
  for (j in 1:5){
    if (i<j & j<= 5){
      mat [upper.tri(mat, diag = FALSE)]<- v
    }
  }
}

但输出是:

       [,1] [,2] [,3] [,4] [,5]
[1,]    0    2    4    2    2
[2,]    0    0    5    4    4
[3,]    0    0    0    5    5
[4,]    0    0    0    0    2
[5,]    0    0    0    0    0

我有两个问题:

  1. 我希望向量在矩阵中只替换一次而不重复。

  2. 我不知道我必须在循环中的哪里替换 i 和 j 以替换矩阵的起点来替换向量。(也许我想从矩阵中的 [3,4] 开始向量。)例如:

      [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    2    4
[4,]    0    0    0    0    5
[5,]    0    0    0    0    0

标签: rmatrixvectorreplace

解决方案


当您从向量填充矩阵时,需要了解两件好事:

  1. 它按列填充它们;和
  2. 如果向量比要填充的矩阵部分短,则向量将被回收(重复)。

此外,在您的代码中,您使用两个for嵌套的循环,其明显意图是仅对矩阵中的这些索引进行操作......但是您没有在矩阵子集或赋值中引用ij,因此每次它尝试替换一个值,它用整个向量替换整个矩阵upper-tri。

这是一个更快的方法:

mat <- matrix(0, nrow = 5, ncol = 5)
v <- c(2, 4, 5)
mat[upper.tri(mat)][seq_along(v)] <- v
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    2    4    0    0
# [2,]    0    0    5    0    0
# [3,]    0    0    0    0    0
# [4,]    0    0    0    0    0
# [5,]    0    0    0    0    0

如您所知,第一个索引mat是上三角形。第二个子集只是length(v)那个子集。

但是,如果您想在上三角形的任意位置替换它,这里有一个镜头:

mat <- matrix(0, nrow = 5, ncol = 5)
ut <- upper.tri(mat)
fullv <- integer(sum(ut)) # the size of the matrix subset
fullv
#  [1] 0 0 0 0 0 0 0 0 0 0
fullv[5 + seq_along(v)] <- v
fullv
#  [1] 0 0 0 0 0 2 4 5 0 0
mat[ut] <- fullv
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    0    0    0    4
# [2,]    0    0    0    0    5
# [3,]    0    0    0    2    0
# [4,]    0    0    0    0    0
# [5,]    0    0    0    0    0

在这里,我们证明填充是由 column完成的,这不是您所要求的。为了更好地了解这种填充是如何发生的,

mat <- matrix(0, nrow = 5, ncol = 5)
ut <- upper.tri(mat)
mat[ut] <- seq_len(sum(ut))
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    1    2    4    7
# [2,]    0    0    3    5    8
# [3,]    0    0    0    6    9
# [4,]    0    0    0    0   10
# [5,]    0    0    0    0    0

因此,如果您希望您v在非常特定的位置并且按照此顺序它们不是连续的,那么您需要具体:

mat <- matrix(0, nrow = 5, ncol = 5)
ut <- upper.tri(mat)
mat[ut][c(6,9,10)] <- v
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    0    0    0    0
# [2,]    0    0    0    0    0
# [3,]    0    0    0    2    4
# [4,]    0    0    0    0    5
# [5,]    0    0    0    0    0

推荐阅读