Search code examples
arraysrmatrixreshape2

Reshape N 2-d matrices (T*M) into a 3d tensor of (T*N*M) with tidyverse/R


For each of my N variables, I have a (T * M) feature matrix, i.e., M observations per t \in T. The problem is how to convert this into a (T * N * M) array. For example, in the following example N=2, T=3, M=4 :

x1 <- matrix(1:24, 3,4)
> x1
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12


x2 <- matrix(25:48, 3,4)
x2
     [,1] [,2] [,3] [,4]
[1,]   25   28   31   34
[2,]   26   29   32   35
[3,]   27   30   33   36

And I need to make a 3 dimensional (number of rows) array, such that the first element is

     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]   25   28   31   34

and the second is:

    [,1] [,2] [,3] [,4]
[1,]    2    5    8   11
[2,]   26   29   32   35

and third:

[,1] [,2] [,3] [,4]
[1,]    3    6    9   12
[2,]   27   30   33   36

and so on and so forth. For the following example, the output's dimensions should be (3,2,4).

I need to do this for relatively large N and T, so appreciate extendable implementations!


Solution

  • Here is a base R option.

    out <- `dim<-`(rbind(c(t(x1)), c(t(x2))), c(2, 4, 3))
    out
    #, , 1
    #
    #     [,1] [,2] [,3] [,4]
    #[1,]    1    4    7   10
    #[2,]   25   28   31   34
    #
    #, , 2
    #
    #     [,1] [,2] [,3] [,4]
    #[1,]    2    5    8   11
    #[2,]   26   29   32   35
    #
    #, , 3
    #
    #     [,1] [,2] [,3] [,4]
    #[1,]    3    6    9   12
    #[2,]   27   30   33   36
    

    When we call x <- rbind(c(t(x1)), c(t(x2))) we get the following matrix as a result

    x
    #     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
    #[1,]    1    4    7   10    2    5    8   11    3     6     9    12
    #[2,]   25   28   31   34   26   29   32   35   27    30    33    36
    

    We need to change the dimensions of this object for which we can do

    dim(x) <- c(2, 4, 3)
    

    Another way to get the same result is to call the replacement method of dim in its functional form, i.e.

    `dim<-`(...)
    

    Which allows us to do all in one line.