Beaker
Beaker

Reputation: 2884

Split matrix into submatrices

I found a solution to a similar question that breaks up a matrix into a set of non-overlapping sub-matrices when the matrix may not be square (as it may not be in my situation) Function to split a matrix into sub-matrices in R. However, in my case I want the matrices to be overlapping. Using the following matrix as an example:

M <- matrix(1:20, 5)

#     [,1] [,2] [,3] [,4]
#[1,]    1    6   11   16
#[2,]    2    7   12   17
#[3,]    3    8   13   18
#[4,]    4    9   14   19
#[5,]    5   10   15   20

If I choose the number of rows and columns of the sub-matrices to be 4 and 4 respectively then the sub-matrices returned should be every possible overlapping 4X4 sub matrix that completely fits within the boundary of the original matrix (this is another place where the answer to this question may need to be different to the question I have referenced). In my example there would only be two sub matrices that should be returned. M[1:4,1:4] and M[2:5,1:4]. I should be able to choose any arbitrary size of sub matrix. I can't seem to find any examples of extracting overlapping sub matrices, but I may be over-thinking this one. Does anyone have any ideas on the best way to go about this?

Upvotes: 3

Views: 2259

Answers (1)

MrFlick
MrFlick

Reputation: 206401

Perhaps a strategy like this could work

submat <- function(m, nrow, ncol) {
    stopifnot(nrow(m)>=nrow, ncol(m)>=ncol)
    rowstarts<-1:(nrow(m)-nrow+1)
    colstarts<-1:(ncol(m)-ncol+1)
    ss <- function(r, c) {
        m[r:(r+nrow-1), c:(c+ncol-1), drop=FALSE]
    }
    with(expand.grid(r=rowstarts, c=colstarts), mapply(ss, r, c, SIMPLIFY=FALSE))
}

submat(M, 4, 4)

we determine where the possible start indexes for the rows and columns are, then we use expand.grid() to generate all possible combinations of such starting values, then we use mapply to extract every possible submatrix with those starting positions.

Upvotes: 4

Related Questions