80960 R: split matrix into arbitrary number of blocks

Say I have a matrix of values

set.seed(1) A <- matrix(runif(25),ncol=5)

I'd like to calculate some statistics for approximately square neighborhoods within this matrix of approximately equal size. Either of these kinds of output would do:

N1 <- matrix(c(rep(c("A","A","B","B","B"),2),rep(c("C","C","D","D","D"),3)),ncol=5) N2 <- matrix(c(rep(c("A","A","A","B","B"),3),rep(c("C","C","D","D","D"),2)),ncol=5) N1 [,1] [,2] [,3] [,4] [,5] [1,] "A" "A" "C" "C" "C" [2,] "A" "A" "C" "C" "C" [3,] "B" "B" "D" "D" "D" [4,] "B" "B" "D" "D" "D" [5,] "B" "B" "D" "D" "D" N2 [,1] [,2] [,3] [,4] [,5] [1,] "A" "A" "A" "C" "C" [2,] "A" "A" "A" "C" "C" [3,] "A" "A" "A" "D" "D" [4,] "B" "B" "B" "D" "D" [5,] "B" "B" "B" "D" "D"

other approximations are also OK, since I can always rotate the matrix. Then I can use these neighborhood matrices to calculate stats using tapply(), like this:

tapply(A,N1,mean) A B C D 0.6201744 0.5057402 0.4574495 0.5594227

What I want is a function that can make me a matrix of arbitrary dimensions with an arbitrary number of block-like neighborhoods like N1 or N2. I'm having a hard time trying to figure out how such a function would deal with situations where the desired number of blocks are not even squares. N1 and N2 have 4 neighborhoods, but say I wanted 5 for some output something like this:

N3 <- matrix(c("A","A","B","B","B","A","A","C","C","C","D","D","C","C","C", "D","D","E","E","E","D","D","E","E","E"),ncol=5) [,1] [,2] [,3] [,4] [,5] [1,] "A" "A" "D" "D" "D" [2,] "A" "A" "D" "D" "D" [3,] "B" "C" "C" "E" "E" [4,] "B" "C" "C" "E" "E" [5,] "B" "C" "C" "E" "E"

Does anyone know of an existing function that can do this kind of split, or have any ideas on how to make one? Thank you!

[] My final function, taking into account Vincent's advice:

DecideBLocks <- function(A,nhoods){ nc <- ncol(A) nr <- nrow(A) nhood_side <- floor(sqrt((nc*nr)/nhoods)) Neighborhoods <- matrix(paste(ceiling(col(A)/nhood_side), ceiling(row(A)/nhood_side), sep="-"), nc=ncol(A)) nhoods.out <- length(unique(c(Neighborhoods))) if (nhoods.out != nhoods){ cat(nhoods.out,"neighborhoods created.\nThese were on average",nhood_side,"by",nhood_side,"cells\nit's a different number than that stated the function tries to round things to square neighborhoods\n") } return(Neighborhoods) } A <- matrix(rnorm(120),12) B <- DecideBLocks(A,13)