3
votes

Suppose I have a square matrix (45 x 45) that I would like to split into 5 sub matrices that are 9 x 9 based off of the diagonal blocks in the matrix. I'm looking for a general way to accomplish this without specifying col and rows.

Example

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

3 Answers

6
votes

Take the kronecker product of the two matrices shown giving a block diagonal matrix m whose first block is all 1's, second block is all 2's, etc. Then split by that, remove the component corresponding to the off-diagonals and re-form each component of the split to a matrix. The result s is a list of the blocks.

# 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)
2
votes

You can use this code to get a list of submatrices.

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]})
2
votes

An option could be by using split and seq to sub-set matrix.

  #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