R: fill multidimensional array line by line

Before presenting the question, I'll point out that something similar has been asked here , but this thread doesn't really answer my question.

Consider the following dimensional arrays:

 1D: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
 2D: [[1,2,3,4,5,6,7,8], [9,10,11,12,13,14,15,16]]
 3D: [[[1,2,3,4],[5,6,7,8]], [[9,10,11,12],[13,14,15,16]]]
 4D: [[[[1,2],[3,4]], [[5,6],[7,8]], [[[9,10],[11,12]], [[13,14],[15,16]]]]
 ...

      

  • 1D array 16 length
  • 2D array is 2x8
  • 3D array - 2x2x4
  • 4D array is 2x2x2x2

Suppose I want to create arrays. For the first two, I could do something similar in R

oneD <- array(1:16, dim=16) # class(oneD) = array
twoD <- array(1:16, dim=8) # class(twoD) = matrix

      

However, the twoD array is now represented as

[[1,3,5,7,9,11,13,15], [2,4,6,8,10,12,14,16]]

      

I know two ways about this.

twoD <- aperm(array(1:16, dim=8))
twoD <- matrix(1:16, nrow=2, byrow=TRUE)

      

However, these methods will not work for filling 3D and 4D arrays. I fill them out below, but I would like them to match my definitions above.

threeD <- array(1:16, dim=c(2,2,4)) # class(threeD) = array
fourD <- array(1:16, dim=c(2,2,2,2)) # class(fourD) = array

      

EDIT

bgoldst's answer made me realize that actually aperm actually works for what I want.

threeD <- aperm(array(1:16, dim=c(2,2,4))
# threeD[1,1,1] = 1
# threeD[1,1,2] = 2
# threeD[1,2,1] = 3
# threeD[1,2,2] = 4
# threeD[2,1,1] = 5
# ....

      

+3


source to share


1 answer


As you wrote your data, you need to fill your arrays first by the deepest dimensions and then by the smaller dimensions. This is the opposite of how R usually populates matrices / arrays.

It also needs to be said that this is slightly different from just filling with a string. To use your 3D array as an illustration of this, you indicated that it needs 4 z-slices, and the innermost "subarrays" are of length 4. This means that you need to fill the z-slices first, then column-wise, then through lines. This is not just filling with a string, but the deepest dimension to the shallow dimension (or at most the least if you prefer). Admittedly, this concept is often referred to as "line by line" or "line order", but I don't like these terms as they are too 2D and they are also misleading IMO as lines are considered to be the smallest size.

To clarify, it's best to think of fill order as dimensions rather than dimensions. Think of an r × c × z cube. If you bump into the front of the cube (that is, referring to the r × c matrix formed from z = 1), if you move along the r = 1 row, that is, from left to right along the top row, then you're also moving along (or inside) z-slice z = 1. The idea of ​​moving in size does not help. But if you think of such movement from left to right as columns, then it is completely unambiguous. So row-by-row means up-and-down, column-by-row means left-right, and z-slices means front-to-back. Another way to think about it is that each respective movement occurs along a dimensional "axis", although I usually don't like to think of it that way because then you have to imagine the idea of ​​axes. Anyway,so I am not interested in the terms "by row" and "row order" (and similar "column order") as the proper way to think of this movement (IMO) is column by column for 2D or through the deepest dimension (followed by more small sizes) for higher dimensions.



You can achieve this requirement by first constructing the resized arrays and then rearranging them to "corrupt" (?) Dimensions. This will allow data to be laid out as needed. Of course, for 1D, no transposition is required, and for 2D we can just use it t()

, but for higher dimensions we will need it aperm()

. And conveniently, when you call aperm()

without specifying an argument perm

, by default it resizes the input; it's like a challenge t()

.

array(1:16,16);
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
t(array(1:16,c(8,2))); ## alternatives: matrix(1:16,2,byrow=T), aperm(array(1:16,c(8,2)))
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]    1    2    3    4    5    6    7    8
## [2,]    9   10   11   12   13   14   15   16
aperm(array(1:16,c(4,2,2))); ## same as aperm(array(1:16,c(4,2,2)),3:1)
## , , 1
##
##      [,1] [,2]
## [1,]    1    5
## [2,]    9   13
##
## , , 2
##
##      [,1] [,2]
## [1,]    2    6
## [2,]   10   14
##
## , , 3
##
##      [,1] [,2]
## [1,]    3    7
## [2,]   11   15
##
## , , 4
##
##      [,1] [,2]
## [1,]    4    8
## [2,]   12   16
##
aperm(array(1:16,c(2,2,2,2))); ## same as aperm(array(1:16,c(4,2,2)),4:1)
## , , 1, 1
##
##      [,1] [,2]
## [1,]    1    5
## [2,]    9   13
##
## , , 2, 1
##
##      [,1] [,2]
## [1,]    3    7
## [2,]   11   15
##
## , , 1, 2
##
##      [,1] [,2]
## [1,]    2    6
## [2,]   10   14
##
## , , 2, 2
##
##      [,1] [,2]
## [1,]    4    8
## [2,]   12   16
##

      

+1


source







All Articles