将上三角矩阵转换为R中的对称矩阵

时间:2017-11-02 18:47:48

标签: r matrix

我有一个20行的数据帧,其中每行是一个10 x 10的上三角形协方差矩阵,带有对角线,我想将其转换为对称的10X10矩阵。我一直关注这个帖子:a vector to an upper Triangle matrix by row in R 但是,当我这样做时,它给了我一个列表而不是矩阵。

此外,我想以递归方式为每一行执行此操作,并将生成的20个矩阵存储在列表中。对于可重现的示例,这里是一个包含20行的数据帧。每行是3x3的具有对角线的上角矩阵。

g <- data.frame(a=runif(20),b=runif(20),c=runif(20),d=runif(20),e=runif(20),f=runif(20))
g1<-c(g[1,])
g2= matrix(0, 3, 3)
g2[upper.tri(g2, diag=TRUE)]=g1
g2
# list of 9 elements instead of matrix
#[[1]]
 # [1] 0.2625916

 # [[2]]
 # [1] 0

 # [[3]]
 # [1] 0

 # [[4]]
 # [1] 0.6255627

 # [[5]]
 # [1] 0.829801

 # [[6]]
 # [1] 0

 # [[7]]
 # [1] 0.3386346

 # [[8]]
  #[1] 0.9517039

 # [[9]]
 # [1] 0.5886387

2 个答案:

答案 0 :(得分:2)

从给定类型的数据开始:

g<-data.frame(a=runif(20),b=runif(20),c=runif(20),d=runif(20),e=runif(20),f=runif(20))

您需要使用函数unlist(...)来更改矩阵中的单个单元格:

> g1<-c(g[1,])
> g2<-matrix(0, 3, 3)
> g2[upper.tri(g2, diag=TRUE)] <- unlist(g1)
> g2
[,1]      [,2]      [,3]
[1,] 0.02287811 0.2938224 0.1224342
[2,] 0.00000000 0.7950484 0.1134449
[3,] 0.00000000 0.0000000 0.7219712

创建上三角矩阵后,可以通过将数据从上三角矩阵元素复制到下三角矩阵元素来使矩阵对称

> g2[lower.tri(g2,diag=FALSE)] <- g2[upper.tri(g2,diag=FALSE)]
> g2
[,1]      [,2]      [,3]
[1,] 0.02287811 0.2938224 0.1224342
[2,] 0.29382240 0.7950484 0.1134449
[3,] 0.12243420 0.1134449 0.7219712

然后可以将原始数据集中的所有矩阵组合在一个列表中,如下所示:

symlist = list()
for (i in 1:dim(g)[1]) {
  g2 <- matrix(0, 3, 3)
  g2[upper.tri(g2,diag=TRUE)] <- unlist(g[i,])
  g2[lower.tri(g2,diag=FALSE)] <- g2[upper.tri(g2,diag=FALSE)]

  symlist[[i]] <- g2
}

例如,这是生成列表中的最后一个矩阵:

> length(symlist)
[1] 20
> symlist[[length(symlist)]]
          [,1]      [,2]      [,3]
[1,] 0.4224727 0.9737866 0.4250256
[2,] 0.9737866 0.7167033 0.2627082
[3,] 0.4250256 0.2627082 0.7556802

答案 1 :(得分:0)

@Heikki的答案仅适用于3x3矩阵(考虑到列填充)

作为一种解决方法,您可以填充上三角部分,转置临时矩阵(这样上三角变成正确的下三角),然后再次填充上三角:

g2[upper.tri(g2, diag=TRUE)] <- unlist(g1)
g2 <- t(g2)
g2[upper.tri(g2, diag=TRUE)] <- unlist(g1)

这也适用于较大的矩阵。示例:

X <- matrix(0, k <- 4, k)
X[upper.tri(X, diag=T)] <- 1:(k*(k+1)/2)
X <- t(X)
X[upper.tri(X, diag=T)] <- 1:(k*(k+1)/2)

     [,1] [,2] [,3] [,4]
[1,]    1    2    4    7
[2,]    2    3    5    8
[3,]    4    5    6    9
[4,]    7    8    9   10