Combining matrices into an array in R
It depends on whether you want to combine them column-major or row-major. This is analogous to using cbind
and rbind
for combining vectors into matrix. Because R stores matrices in column-major order, this is the easiest to accomplish:
matrices <- list(
matrix( 1:9 , 3 , 3 ),
matrix( 10:18 , 3 , 3 )
);
#it is assumed all matrices in the list have equal dimensions
array1 <- array(
data = do.call(cbind, matrices),
dim = c(dim(matrices[[1]]), length(matrices))
);
The new dimension (2 in this case) will become the 3rd dimension. Judging from the output of the print method, this looks accurate, because it splits the print by the last dimension:
> print(array1)
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
[3,] 12 15 18
However, sometimes you might need to combine them by the first dimension instead, e.g:
array2 <- array (
data = do.call(rbind, lapply(matrices, as.vector)),
dim = c(length(matrices), dim(matrices[[1]]))
);
print(array2[1,,])
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
For example, say you want to assign these matrices to a data frame with column; one matrix for each row. Then the first dimensions, a.k.a nrow
have to match in the array and data frame:
mydf <- data.frame(foo = 1:2, row.names=c("first", "second"))
mydf$bar <- array1
Error in `$<-.data.frame`(`*tmp*`, "bar", value = 1:18) :
replacement has 3 rows, data has 2
mydf$bar <- array2
mydf$bar
The short version is that you can simplify-to-array a set of matrices using the function: simplify2array
:
simplify2array(list(x,y))
Below is my previous answer showing how to do this with sapply
's simplify=
argument, since ‘simplify2array()’ is the utility called from ‘sapply()’ when ‘simplify’ is not false - see the ?sapply
help file.
Here's a version similar to abind
-ing, but without using any additional packages. Collect everything into a list
and then use sapply
's option to simplify=
to an "array"
, after doing nothing to each part of the list (identity
just returns the object and is equivalent to function(x) x
):
sapply(list(x,y), identity, simplify="array")
# similarly to save a couple of keystrokes, the following is usually identical
sapply(list(x,y), I, simplify="array")
#, , 1
#
# [,1] [,2] [,3]
#[1,] 1 4 7
#[2,] 2 5 8
#[3,] 3 6 9
#
#, , 2
#
# [,1] [,2] [,3]
#[1,] 10 13 16
#[2,] 11 14 17
#[3,] 12 15 18
If you want to retain the names of each original matrix in your new array as identifiers, try:
sapply(mget(c("x","y")), identity, simplify="array")
here's the example for two. you can easily extend this to eight
# create two matricies with however many rows and columns
x <- matrix( 1:9 , 3 , 3 )
y <- matrix( 10:18 , 3 , 3 )
# look at your starting data
x
y
# store both inside an array, with the same first two dimensions,
# but now with a third dimension equal to the number of matricies
# that you are combining
z <- array( c( x , y ) , dim = c( 3 , 3 , 2 ) )
# result
z
You can use the abind
function from the abind
package:
library(abind)
newarray <- abind( mat1, mat2, mat3, mat4, along=3 )
## or if mats are in a list (a good idea)
newarray <- abind( matlist, along=3 )