2015-07-31 3 views
3

Прежде чем представить вопрос, я укажу, что что-то подобное было задано here, но эта тема на самом деле не отвечает на мой вопрос.R: Заполнить многомерный массив по строке

Рассмотрим следующие одномерные массивы:

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 является длина 16
  • 2D-массив 2x8
  • 3D-массив 2x2x4
  • Массив 4D является 2x2x2x2

Предположим, я хочу создать массивы. Для первых двух, я мог бы сделать что-то подобное в R

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

Однако массив twoD теперь представлен в виде

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

Я знаю двух способов обойти это.

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

Однако эти методы не будут работать для заполнения трехмерных и четырехмерных массивов. Я их заполняю ниже, но я бы хотел, чтобы они соответствовали моим определениям выше.

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 заставил меня понять, что на самом деле АПРОН делает работу за то, что я хочу.

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 
# .... 
+0

Являются ли они называемыми массивами? Они кажутся больше похожими на деревья из того, как они структурированы. – VermillionAzure

+0

Возможно, что-то с 'length()' может вам помочь? – VermillionAzure

+0

Вы, кажется, думаете с множеством доминирующих состояний. Если вы работаете с R, вы должны думать о матрице и конструкции массива как о столбце-ориентированном, –

ответ

1

, как вы написали ваши данные, вам необходимо заполнить ваши массивы через глубочайшего измерения первого, а затем через более мелкие размеры. Это противоположно тому, как R обычно заполняет матрицы/массивы.

Следует также сказать, что это немного отличается от простого заполнения рядом. Чтобы использовать ваш 3D-массив в качестве иллюстрации этого, вы указали, что ему требуются 4 z-среза, а самые внутренние «подмассивы» имеют длину 4. Это означает, что вам нужно сначала заполнить z-срезы, затем по столбцам, затем через строк. Это не просто заполнение по строке, но по глубочайшему размеру до неглубокого размера (или, самое большее, по крайней мере, если вы предпочитаете). По общему признанию, эта концепция часто упоминается как «по строке» или «порядок строк», но мне не нравятся эти термины, поскольку они слишком 2D, и они также вводят в заблуждение ИМО, поскольку строки считаются быть неглубоким измерением.

Выработать: Лучше думать о порядке заполнения как через размеры, а не вдоль размеров. Подумайте об r × c × z куб.Если вы лицом к передней части кубы (то есть, с видом на матрицу г × с, образованной из г = 1), при перемещении вдоль строки г = 1, то есть, от слева направо вдоль верхнего ряда, то вы также перемещаете по адресу (или в пределах) z-slice z = 1. Идея перемещения по измерению не помогает. Но если вы думаете о таком движении слева направо как через столбцов, то это совершенно однозначно. Таким образом, по строкам означает вверх-вниз, по столбцам означает левый-правый, а через z-срезы - фронт-назад. Другой способ думать об этом - каждое соответствующее движение происходит по размерной «оси», хотя мне обычно не нравится думать об этом таким образом, потому что тогда вам нужно представить идею топоров. Во всяком случае, поэтому меня не интересуют термины «по ряду» и «порядок строк» ​​(и аналогичный «порядок столбцов»), поскольку надлежащий способ думать об этом движении (IMO) равен через столбцы для 2D или через самый глубокий размер (за которым следует более мелкие размеры) для более высоких размерностей.

Вы можете достичь этого требования, сначала построив массивы с измененной размерностью, а затем переставив их в «развороты» (?) Размерности. Это позволит выложить данные по мере необходимости. Конечно, для 1D транспонирование не требуется, и для 2D мы можем просто использовать t(), но для более высоких измерений нам понадобится aperm(). И удобно, когда вы вызываете aperm() без указания аргумента perm, по умолчанию он меняет размерность ввода; это как звонок 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 
## 
+0

Спасибо - я высоко оценил ваше объяснение порядка заполнения по размерам, и функция аперма была тем, что я искал. Я не понимал, что R всегда сначала заполняет мелкие размеры. – nathanesau

Смежные вопросы