I'm struggling to split a matrix without using loops. I want to split a 9x9 matrix into nine 3x3 matrices (not overlaping). I tried using split()
passing a vector as the "factor" grouping without success. Also tried using asplit()
without success. I think I don't understand how "MARGIN" works on asplit()
. I can get the 3x3 "cubes" using loops, but I'm just wondering if there's a way to do it with simple utility functions.
m <- matrix(1:81, 9, 9)
I want to store the 9 resulting 3x3 matrices in a list. The expected result for first cube is:
cube[[1]]
[,1] [,2] [,3]
[1,] 01 10 19
[2,] 02 11 20
[3,] 03 12 21
I tried
# all these split by row
indices <- matrix(1:9, 3, 3)
cubes <- split(m, as.vector(indices))
indices <- array(1:9, dim = c(3, 3, 9))
cubes <- split(m, as.vector(indices))
indices <- array(matrix(1:9, 3, 3), dim = c(3, 3, 9))
cubes <- split(m, as.vector(indices))
# this gives an error
asplit(m, MARGIN = c(3,1))
There is a function as.blockmatrix
in package blockmatrix
that does this. Although the function is written in base R and uses for-loops
blockmatrix::as.blockmatrix(m, 3,3)
If you want to use base R, you could write your own function as follows:
blocks <- function(x, nr, nc){
c(tapply(x, list((row(x) - 1)%/%nr, (col(x) - 1)%/%nc), array, c(nr, nc)))
}
blocks(m, 3, 3)
playing around with aperm
was able to get the below code to work:
c(asplit(aperm(array(m, c(3,3,3,3)), c(1,3,4,2)), 3:4))