Search code examples
rarraysmatrixdata-conversion

Convert R 3D array to stacked matrix


I have a 3D R array, e.g.:

a <- array(1:27, dim = c(3,3,3))

How can I (efficiently) convert this into a matrix in which the 3rd dimension is bound / stacked below each other, i.e.:

      [,1] [,2] [,3]
 [1,]    1    4    7
 [2,]    2    5    8
 [3,]    3    6    9
 [4,]   10   13   16
 [5,]   11   14   17
 [6,]   12   15   18
 [7,]   19   22   25
 [8,]   20   23   26
 [9,]   21   24   27

I can clumsily achieve this with:

rbind(a[,,1], a[,,2], a[,,3])

but this is not generalizable well if I have many entries in the 3rd dimension (except with looping). There must be a more elegant way to achieve this, but I could not find it. Ideas like

apply(a, 3, rbind)
apply(a, 3, c)

create a matrix, but the 3rd dimension simply become the columns. I want to keep the 2D matrices of the first 2 dimensions and just bind them together. I am aware this will mess up the indices, but we can disregard this for my use case.

I would be especially happy about a base R solution, but am also interested if this can be achieved with a (lightweight) package.

Edit: This answer to a seemingly unrelated question provided a useful hint. This approach seems to achieve the desired result:

matrix(aperm(a, c(1, 3, 2)), nrow = dim(a)[1] * dim(a)[3])

Are there other ideas?


Solution

  • With aperm we transpose an array by permuting its dimensions and optionally resizing it:

    y <- aperm(a, c(1, 3, 2))
    dim(y) <- c(prod(dim(a)[-2]), dim(a)[2])
    
    y
    
           [,1] [,2] [,3]
     [1,]    1    4    7
     [2,]    2    5    8
     [3,]    3    6    9
     [4,]   10   13   16
     [5,]   11   14   17
     [6,]   12   15   18
     [7,]   19   22   25
     [8,]   20   23   26
     [9,]   21   24   27