按对角块拆分正方形矩阵

3
假设我有一个正方形矩阵(45 x 45),我想将其分成5个子矩阵,这些子矩阵基于矩阵中的对角块,并且每个子矩阵的大小为9 x 9。 我正在寻找一种通用的方法来完成此操作,而不需要指定列和行。 示例
mat <- matrix(rnorm(45), 45, 45)

mat1 <- mat[1:9, 1:9]
mat2 <- mat[10:18, 10:18]
mat3 <- mat[19:27, 19:27]
mat4 <- mat[28:36, 28:36]
mat5 <- mat[37:45, 37:45]
3个回答

6

对于两个矩阵,取其Kronecker积得到一个分块对角矩阵 m,其中第一块为全部为1,第二块为全部为2,以此类推。接着按该矩阵进行拆分,删除与非对角线相应的部分,并将每个拆分组件重新形成一个矩阵。结果s是一个块列表。

# test inputs
set.seed(123)
n <- 45
k <- 9
mat <- matrix(round(rnorm(n*n), 2), n, n)


m <- diag(1:(n/k)) %x% matrix(1, k, k) 
s <- lapply(split(mat, m)[-1], matrix, k)

了解“克罗内克积”是很好的。 - MKR
太棒了!谢谢。 - Vedda

2
您可以使用此代码获取子矩阵列表。
mat <- matrix(rnorm(45), 45, 45)

mat.size <- ncol(mat)
num.sub <- 5
sub.size <- mat.size/num.sub

sub.matrices <- lapply(1:num.sub, function(x){
  locations <- ((x-1)*sub.size+1):(x*sub.size) 
  mat[locations, locations]})

最初我也是和你想得一样。你很快就找到了解决方案,让我不得不寻找替代方案。不错。 - MKR

2
一种方法是使用 splitseq 来子集化矩阵。
  #Using same data as by @G.Grothendieck
  set.seed(123)
  n <- 45
  k <- 9
  mat <- matrix(round(rnorm(n*n), 2), n, n)

  lapply(split(seq(n), rep(1:(n/k), each = k)), function(x)mat[x,x])

  # $`1`
  # [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]
  # [1,] -0.56 -1.12  0.99  1.13 -1.06  0.06  0.85  0.70 -0.21
  # [2,] -0.23 -0.40  0.55 -1.46  1.26 -0.70  0.96 -0.11  0.65
  # [3,]  1.56 -0.47  0.24  0.74 -0.35 -0.72  0.68 -1.26  0.27
  # [4,]  0.07  0.78 -0.63  1.91 -0.87  0.88 -1.40  1.68  1.02
  # [5,]  0.13 -0.08  1.36 -1.44 -0.24 -1.02  0.85  0.91  0.82
  # [6,]  1.72  0.25 -0.60  0.70 -0.20  1.96 -0.45  0.24 -0.21
  # [7,]  0.46 -0.03  2.19 -0.26  1.11 -0.09  0.17  1.22  0.38
  # [8,] -1.27 -0.04  1.53 -1.57  0.08  0.21  0.07 -1.34 -0.95
  # [9,] -0.69  1.37 -0.24 -1.51  0.75 -0.74  0.43  0.66  0.86
  # 
  # $`2`
  # [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]
  # [1,] -0.41 -0.30 -1.51 -0.56  0.50 -0.49 -1.04  0.99  0.28
  # [2,] -2.64  0.87 -0.10  0.84 -1.16 -0.83 -0.41  1.74  1.88
  # [3,] -0.09 -0.35 -0.90 -0.78 -0.13  0.27 -0.24  0.88  0.00
  # [4,]  0.43  0.52 -2.07  1.11 -1.94  0.16  0.48 -1.94 -0.28
  # [5,]  0.54 -0.39  0.15  0.25  1.18  0.63 -0.32  1.40  0.47
  # [6,] -0.56 -1.09 -0.08  1.65  1.86 -0.40 -2.08 -0.06 -0.28
  # [7,]  1.78  1.21 -0.10 -1.46  1.07  0.90 -0.09  0.52  0.81
  # [8,]  0.29  0.74  0.22 -0.05 -0.03 -0.83  1.19  0.62  0.90
  # [9,]  0.13  1.72  0.88 -0.53 -0.03 -0.33  1.19 -0.10  0.00
  # 

  #...
  #.....
  #......so on 

@G.Grothendieck非常感谢您指出那个愚蠢的错误。在看到您的评论之前,我没有意识到这一点。我正在进行更正。 - MKR
@G.Grothendieck 我应该将我的答案与您的结果匹配。我认为我已经匹配了一些点(也许是角落的点):-( - MKR

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