Replicating 2 dimensional matrix to create a 3 dimensional array (in R) - arrays

I have a two dimensional matrix that I would like to replicate 10 times to create a three dimensional array where each 'slice' of the array is an identical copy of the two dimensional array.
So, if my 2D array were to be:
a <- matrix(c(1:4),nrow=2)
> a
[,1] [,2]
[1,] 1 2
[2,] 3 4
I would like as output an array like this:
, , 1
[,1] [,2]
[1,] 1 2
[2,] 3 4
, , 2
[,1] [,2]
[1,] 1 2
[2,] 3 4
....
, , 10
[,1] [,2]
[1,] 1 2
[2,] 3 4
I have seen this page (Duplicate matrix to form list), in which the OP was looking to duplicate matrices to a list, which I adapted to then convert to an array:
b<-rep(list(a), 10) # from original post
array(unlist(b), dim = c(nrow(b[[1]]), ncol(b[[1]]), length(b))) # line I added
This works fine but it's a little roundabout - I was wondering if there were a way to do this in one line without going through the creation of a list.
I tried applying the logic of a do.call in the way that is done with rbind to bind multiple rows together, but using abind instead -
do.call(abind,as.list(c(a,a,a,a,a,a,a,a,a,a)))
but the output was one long vector and so not what I was looking for.
Any help is greatly appreciated!

you can use replicate, which produces a list by default. To get an array, add simplify = "array".
replicate(10, a, simplify="array")
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 1 3
[2,] 2 4
...
, , 9
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 10
[,1] [,2]
[1,] 1 3
[2,] 2 4

Related

Apply function for multidimensional array in R to find the mean for each column at each array

z <- array(1:12, dim = c(2,2,3))
z
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
, , 3
[,1] [,2]
[1,] 9 11
[2,] 10 12
For the above array of 3 matrices, I would like to create one single matrix by taking the mean values of each column for each array. So my expected matrix dimension should be 3 by 2. The first entry should be the mean of 1 & 2. The second entry of the first row is the mean of 3 & 4.
Can I use any apply function or any loop to create the matrix?
Appreciate your help.

ordering a "window" of a multidimensional array

I'm new to R and this is my first question (apologies if the question is posed wrongly).
I would like to change the order of the rows accordingly to the values by the columns of a "window" inside a multidimensional array.
Here's a simplified example:
x1<-matrix(c(1,3,2,4), 2)
x1
[,1] [,2]
[1,] 1 2
[2,] 3 4
x2<-matrix(c(7,5,8,6),2)
x2
[,1] [,2]
[1,] 7 8
[2,] 5 6
x3<-array(c(x1,x2), dim = c(2,2,2))
I would then like to re-arrange the first "window" of the array so that it will be like x4:
x4<-x1[order(x1[,1], decreasing = TRUE),]
x4
[,1] [,2]
[1,] 3 4
[2,] 1 2
How can I do that inside the array?
Plus, will the change affect also all the other "windows" in the array?
So that, in the end, I will end up with an array like this:
x3[,,1]
[,1] [,2]
[1,] 3 4
[2,] 1 2
x3[,,2]
[,1] [,2]
[1,] 5 6
[2,] 7 8
Thanks a lot!
You are trying to reorder the rows (1st dimension) of the array; It is similar to how you will reorder the rows of a matrix except that it is 3d so you need to specify three indices:
x3[order(x3[,2,1], decreasing = T),,]
#, , 1
# [,1] [,2]
#[1,] 3 4
#[2,] 1 2
#, , 2
# [,1] [,2]
#[1,] 5 6
#[2,] 7 8

Sum of matrices in 3-dimensional object of variable dimensions without looping

I have a 3-dimensional object in R, which contains n square matrices. For example:
myObject[,,1] # returns a square matrix
myObject[,,2] # returns a square matrix of the same size
...
All the matrices within the object are of the same size. I'd like to add all matrices together, without a loop. This is simple enough if I know how many matrices are in the object. For example:
matrixSum <- myObject[,,1] + myObject[,,2] + myObject[,,3]
The problem is, I need to do this for several thousand such objects, and there are a variable number of matrices in each object. Is there any way I can do this without a loop? In a sense, I'd like to try to "vectorize" this summation.
The most convient, but certainly not the fastest, is to use apply:
matrixSum <- apply(myObject, c(1,2), sum)
Example
myObject <- array(c(1,2,3),dim = c(3,4,3))
myObject
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
, , 2
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
, , 3
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
apply(myObject, c(1,2), sum)
[,1] [,2] [,3] [,4]
[1,] 3 3 3 3
[2,] 6 6 6 6
[3,] 9 9 9 9
Addition:
Using rowSums should be must faster:
rowSums(myObject, dims = 2)
[,1] [,2] [,3] [,4]
[1,] 3 3 3 3
[2,] 6 6 6 6
[3,] 9 9 9 9

R filling array by rows

I would like to do some matrix operations and it would be best to utilize 3 (or higher) dimensional arrays. If I want to fill matrices by row there is an argument (byrow = TRUE) however there is no such option for creating/filling a multidimensional array. The only way I've been able to accomplish it is by using aperm to transpose an array that was filled by column. For example:
arr.1 <- array(1:12, c(3,2,2))
arr.1
arr.2 <- aperm(arr.1, c(2,1,3))
arr.2
produces the correct result, a dimension 2,3,2 array that is filled by row. It seems a bit counter intuitive to have to work backward from a Column x Row x Range array to get to a Row x Column x Range array. This might be bad habits from previous f77 coding or have I overlooked something simple?
Arrays in R are filled in by traversing the first dimension first. So first the first dimension is traversed, then the second dimension, and then third dimension if it is available.
In case of a matrix:
array(c(1,2,3), dim = c(3,3))
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
Or with assignment:
M <- array(dim = c(3,3))
M[,] <- c(1,2,3)
M
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
Assigning to the second dimension is easy:
M <- array(dim = c(3,3))
M[,2:3] <- c(1,2,3)
M
[,1] [,2] [,3]
[1,] NA 1 1
[2,] NA 2 2
[3,] NA 3 3
But assigning to first dimension is more tricky. The following doesn't give the expected result:
M <- array(dim = c(3,3))
M[2:3,] <- c(1,2,3)
M
[,1] [,2] [,3]
[1,] NA NA NA
[2,] 1 3 2
[3,] 2 1 3
Data is filled by first traversing the first dimension, then second. What we want is to first traverse the second dimension, then first. So we have to aperm the array (or transpose in case of matrix).
M <- array(dim = c(3,3))
Mt <- aperm(M)
Mt[,2:3] <- c(1,2,3)
M <- aperm(Mt)
M
[,1] [,2] [,3]
[1,] NA NA NA
[2,] 1 2 3
[3,] 1 2 3
There are maybe more elegant ways to do the last which I am not aware of.
If you want to interpret a vector of values as an n-dimensional array in "row-major order" (as in C, or more precisely, last dimension varying fastest), you can use function array2() from package listarrays. This is the logical extension of matrix(..., byrow = TRUE) to multiple dimensions.
Compare base R
> (a <- array(1:24, c(2,3,4)))
, , 1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
, , 2
[,1] [,2] [,3]
[1,] 7 9 11
[2,] 8 10 12
, , 3
[,1] [,2] [,3]
[1,] 13 15 17
[2,] 14 16 18
, , 4
[,1] [,2] [,3]
[1,] 19 21 23
[2,] 20 22 24
with
> library(listarrays)
> (a <- array2(1:24, c(2,3,4)))
, , 1
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 13 17 21
, , 2
[,1] [,2] [,3]
[1,] 2 6 10
[2,] 14 18 22
, , 3
[,1] [,2] [,3]
[1,] 3 7 11
[2,] 15 19 23
, , 4
[,1] [,2] [,3]
[1,] 4 8 12
[2,] 16 20 24
My recommendation would be to "teach" yourself the default order by running
foo<- array(1:60,3,4,5)
Then you can fill an arbitrary array either by rearranging your source vector or by creating matrices and loading them into the z-layers of the array in the order desired.

Converting a complicated list of matrices into an array of matrices

I would like to convert a list of matrices into an array of stapled matrices. My list looks like l3 in:
getme<-matrix(1,3,3)
getme2<-matrix(2,4,4)
l1<-list(getme,getme2)
names(l1)<-c('getme','getme2')
getme<-matrix(3,3,3)
getme2<-matrix(4,4,4)
l2<-list(getme,getme2)
names(l2)<-c('getme','getme2')
l3<-list(l1,l2)
The goal is to append each conformable matrix into an array. The name of the array/variable should be equal to the name of the level of the list.
So for example:
getme<-array(dim=c(3,3,2))
m=2
for(i in 1:m){getme[,,i]<-l3[[i]]$getme}
Since my lists get vary large in terms of both mand number of getmematrices, I need to automatize this procedure across all m levels of the list l3. Ideally I would want code that produces j arrays getme, getme2,...getme_j, where only l3is used as an input. That is the names of the variable levels, names(l3[[1]]), are applied on the way.
The combination of matrices into arrays is easy with abind from the abind package:
library(abind)
res <- lapply(seq_along(l3[[1]]), function(x)
abind(lapply(l3, "[[", x), along = 3))
The outer lapply function is used to apply a function to the numbers form 1 to the length of the list l3. The current number is represented by parameter x. The other lapply command is used to extract the xth element from the list l3. These elements are combined into an array with abind. Since the length of l3 is 2, the outer lapply returns a list of length 2.
This returns a list of arrays:
[[1]]
, , 1
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 1 1
[3,] 1 1 1
, , 2
[,1] [,2] [,3]
[1,] 3 3 3
[2,] 3 3 3
[3,] 3 3 3
[[2]]
, , 1
[,1] [,2] [,3] [,4]
[1,] 2 2 2 2
[2,] 2 2 2 2
[3,] 2 2 2 2
[4,] 2 2 2 2
, , 2
[,1] [,2] [,3] [,4]
[1,] 4 4 4 4
[2,] 4 4 4 4
[3,] 4 4 4 4
[4,] 4 4 4 4
You can use the original names with
names(res) <- names(l3[[1]])

Resources