如何从矩阵中删除对角元素的平方?

4
我们可以使用diag()函数来删除矩阵的对角线元素,但如果我们想要删除对角线上的正方形元素怎么办?就像在一个6x6的矩阵中,我想要删除对角线上2x2的正方形。这看起来非常基础,但如何在r中实现呢?
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   23   98   12   98   32   99
[2,]   54   11   13   02   31   78
[3,]   25   85   15   09   46   87
[4,]   98   98   16   17   45   48
[5,]   88   00   68   99   89   89
[6,]   05   33   66   12   14   78

我希望将对角线的方格设置为NA。

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   NA   NA   12   98   32   99
[2,]   NA   NA   13   02   31   78
[3,]   25   85   NA   NA   46   87
[4,]   98   98   NA   NA   45   48
[5,]   88   00   68   99   NA   NA
[6,]   05   33   66   12   NA   NA

先移除所有的NAs,然后再将列合并

     [,1] [,2] [,3] [,4]
 [1,]  12   98   32   99
 [2,]  13   02   31   78
 [3,]  25   85   46   87
 [4,]  98   98   45   48
 [5,]  88   00   68   99
 [6,]  05   33   66   12

如何移除它?移除后剩下什么?为了帮助,请附上一个可复制的示例,包括样本输入和期望输出。 - MrFlick
3个回答

4

我希望有更优雅的方法来做这件事,但这是一种方法:

# Create a matrix
mat = matrix(1:36, nrow=6)

# Set block diagonal elements to NA
for (i in seq(1, nrow(mat), 2)) {
  mat[i:(i+1),i:(i+1)] = NA
}

# Reform the matrix with the NA values excluded
matrix(mat[!is.na(mat)], nrow=nrow(mat)-2)

2
您可以使用Kronecker乘积快速构建一个块对角矩阵,指示哪些元素需要保留,哪些需要删除。
## An example matrix
set.seed(1)
m <- matrix(sample(1:100, 36), ncol=6)

## Construct a logical block diagonal matrix, then use it to remove blocks along diagonal
ii <- !kronecker(diag(1, nrow(m)/2), matrix(1, ncol=2, nrow=2))
matrix(m[ii], ncol = ncol(m)-2)
##      [,1] [,2] [,3] [,4]
## [1,]   57   19   32    1
## [2,]   89   16   63   28
## [3,]   20   61   51   87
## [4,]   86   34   10   42
## [5,]   58   88   21   70
## [6,]    6   83   29   13

2

我们在一个列表中创建了3个值为1的矩阵,使用bdiag构建一个分块对角线矩阵,双重否定将二进制强制转换为逻辑值,用NA替换TRUE元素,乘以'm1'得到'm2'。

library(Matrix)
m2 <- as.matrix((NA^!!bdiag(lapply(1:3, matrix, data=1,ncol=2, nrow=2)))*m1)
m2
#      [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]   NA   NA   12   98   32   99
#[2,]   NA   NA   13    2   31   78
#[3,]   25   85   NA   NA   46   87
#[4,]   98   98   NA   NA   45   48
#[5,]   88    0   68   99   NA   NA
#[6,]    5   33   66   12   NA   NA

我们使用applyMARGIN=1来删除每行中的NA元素,以获得期望的输出结果。
t(apply(m2, 1, function(x) x[!is.na(x)]))
 #      [,1] [,2] [,3] [,4]
#[1,]   12   98   32   99
#[2,]   13    2   31   78
#[3,]   25   85   46   87
#[4,]   98   98   45   48
#[5,]   88    0   68   99
#[6,]    5   33   66   12

数据

m1 <- structure(c(23L, 54L, 25L, 98L, 88L, 5L, 98L, 11L, 85L, 98L, 
0L, 33L, 12L, 13L, 15L, 16L, 68L, 66L, 98L, 2L, 9L, 17L, 99L, 
12L, 32L, 31L, 46L, 45L, 89L, 14L, 99L, 78L, 87L, 48L, 89L, 78L
), .Dim = c(6L, 6L))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接