Jim Maas
Jim Maas

Reputation: 1729

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?

Upvotes: 7

Views: 10317

Answers (3)

Edward
Edward

Reputation: 486

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

Upvotes: 1

Davor Josipovic
Davor Josipovic

Reputation: 5504

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.

Upvotes: 1

Carl Witthoft
Carl Witthoft

Reputation: 21502

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.

Upvotes: -1

Related Questions