If I have several matrices that I have created, how can I combine them into one array? I have 8 matrices that each have 200 rows and 200 columns and I need to combine them into an array with dim = 200,200,8. So I want each of my matrices to be a slice of my array.
7 に答える
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 )
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
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")
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
library('abind')
abind(m1, m2, m3, along = 2.5)
abind(m1, m2, m3, along = 3)
m4 <- list(m1, m2, m3)
abind(m4, along = 3)
along input = matrix + matrix output
----------------------------------------------------------------------------
0 split columns and row bind them array
0.5 same as 0 array
1 combine matrices into one matrix by rowwise matrix
1.5 split columns and column bind them array
2 combine matrices into one matrix by columnwise matrix
2.5 Form an array with matrices array
3 Same as 2.5 array
How about this:
combmat <- array(dim=c(200,200,8), data=cbind(matrix1,matrix2,...,matrix8) )
Related: How to stack multiple matrices in R
The problem with all solutions so far is that when matrices (not data.frame
s - for this dplyr
and data.table
work fine) do not have the same order of rows and columns, bind will stack values over each other that do not relate.
If you want to check and take into account the names in each dimension, have a look at narray
:
(disclaimer: I wrote the package)