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!

[[Edit]] 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)


You can try to play with the row and col functions: they reduce the problem to a 1-dimensional one. The following defines blocks of size at most 2*2.

matrix( paste( ceiling(col(A)/2), ceiling(row(A)/2), sep="-"), nc=ncol(A) )


You can choose your bdeep (row-spec) and bwide (co-spec) parameters near the center of youree matrix dimensions in whatever manner you like and use this simple function to construct your matrix. As long as the bwide and bdeep are equal, and nrow==ncol, you should get square sub-matrices.

mkblk <- function(bwide, bdeep, nrow, ncol){ bstr1 <- c(rep("A", bdeep), rep("B", nrow-bdeep)) bstr2 <- c(rep("C", bdeep), rep("D", nrow-bdeep)) matrix(c( rep(bstr1, bwide), rep(bstr2, ncol-bwide)), ncol=ncol, nrow=nrow)} mkblk(2,2,5,5) [,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" #Test of your strategy tapply(A, mkblk(2,2,5,5), mean) A B C D 0.6201744 0.5057402 0.4574495 0.5594227


  • Java Class Generics and Method Generics conflicts
  • printing a float with runtime-selectable precision
  • How do I have bash “eat” indentation characters common to all lines in a string?
  • How to find via Python the icon associated with a Windows file?
  • Spring Integration TCP. Get connection ID of the connected clients
  • convert std::ostream to some array?
  • Hash UUIDs without requiring ordering
  • python flexible, inline variable assignment
  • How do you balance Auto Layout with creating frames?
  • How to asynchronously apply function via Spark to subsets of dataframe?
  • apply parent's hover to jquery ui autocomplete child
  • Python functions: Pass global variables if only accessing them?
  • Problem glTexGen in Open GL ES 2.0
  • dc.js: Reducing rows in data table
  • Use of qualified name in function parameter
  • drop duplicates pandas dataframe
  • PHP: Very simple Encode/Decode string
  • Calling C function from lua
  • How to request unsampled report from Google Analytics Management API using Google Apps Script?
  • Responsive left sidebar open close
  • Prevent page break in text block with iText, XMLWorker
  • cell spacing in div table
  • C++ friend class std::vector
  • How to access meteor package name inside package?
  • XSLT foreach repeating nodes to flat
  • How to create a 2D image by rotating 1D vector of numbers around its center element?
  • SyntaxError: (irb):26: both block arg and actual block given
  • How to get latest version of a artifact on Bintray using JSONP
  • Tell Git to stop prompting me for conflicts when none really exist?
  • Thread 1: EXC_BAD_ACCESS (code =1 address = 0x0)
  • Is there a javascript serializer for JSON.Net?
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Where to put my custom functions in Wordpress?
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • Buffer size for converting unsigned long to string
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • How can I remove ASP.NET Designer.cs files?
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • Running Map reduces the dimensions of the matrices
  • Binding checkboxes to object values in AngularJs