2016-05-02 2 views
2

Я пытаюсь эффективно сгенерировать массив на основе имени измерения.Совокупность массива на основе имен измерения

ex_array <- array(1:10000, dim = c(100, 10, 10), 
        dimnames = list(Col1 = c(rep(10,50), rep(20, 50)), 
            Col2 = 1:10, 
            Col3 = 1:10)) 

Теперь я хочу объединить этот массив на основе имен первого измерения. Этот размер имеет 2 разных имени (10 и 20), и поэтому новый массив должен иметь размер 2 на 10 на 10. Все значения с именем измерения 1, равным 10, должны быть суммированы, а значения с размером 1, равным 20, должны суммироваться.

Есть ли какой-нибудь умный способ сделать это?

ответ

2

reshape2. Я думаю reshape2 лучше подходит здесь, если вы готовы использовать пакеты:

library(reshape2) 
res = acast(melt(ex_array), Col1 ~ Col2 ~ Col3, fun.aggregate = sum) 

str(res) 
# int [1:2, 1:10, 1:10] 1275 3775 6275 8775 11275 13775 16275 18775 21275 23775 ... 
# - attr(*, "dimnames")=List of 3 
# ..$ : chr [1:2] "10" "20" 
# ..$ : chr [1:10] "1" "2" "3" "4" ... 
# ..$ : chr [1:10] "1" "2" "3" "4" ... 

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


база R. Вы можете использовать rowsum, но неуклюжим здесь, потому что он предназначен для матриц

res2 = array(, c(2, 10, 10), dimnames = lapply(dimnames(ex_array), unique)) 
res2[] = sapply(seq_len(dim(ex_array)[3]), function(k) 
    rowsum(ex_array[,,k], rownames(ex_array[,,k]))) 
+1

Как я выполнял свои махинации, я подумал про себя, что это, вероятно, будет выглядеть гораздо более компактным, если выполняются функциями 'reshape2' или' splitstackshape' или 'dplyr'. (И он обеспечивает то, что я считаю правильным результатом.) –

2

Чтобы сделать это лишь один из имен измерений, это может быть просто:

apply(ex_array[dimnames(ex_array)[[1]] == "10",,], 2:3, sum) 

Если вы затем обернуть, что в sapply вызова вы получаете 2 x prod(N1, N2) матрицу с соответствующей информацией. Я работал с сморщенной версией вашего примера набора данных:

ex_array <- array(1:360, dim = c(10, 6, 6), 
        dimnames = list(Col1 = c(rep(10,5), rep(20,5)), 
            Col2 = 1:6, 
            Col3 = 1:6)) 
str(sapply(unique(dimnames(ex_array)[[1]]), function(x) apply(ex_array[dimnames(ex_array)[[1]] == x,,], 2:3, sum))) 
int [1:36, 1:2] 15 65 115 165 215 265 315 365 415 465 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : NULL 
    ..$ : chr [1:2] "10" "20" 

.... но это в столбцах порядка и переделать его к 2 х N1 х N2 массиву, то нужно перенести его, так Значения «10» - это верхняя строка, а значения «20» - это вторая строка. Затем эти значения могут быть пересчитаны в массив 2 x N1 xN2. Вы можете думать об этом как первом размещении «10» значение в правильном срезе координаты, а затем путем размещения «20» значение коорда, и так далее, и так далее:

target <- array(t( # need to process the transpose 
       sapply(unique(dimnames(ex_array)[[1]]), 
        function(x) apply(ex_array[dimnames(ex_array)[[1]] == x,,], 2:3, sum)) 
        ), 
       dim= c(length(unique(dimnames(ex_array)[[1]])), dim(ex_array)[2:3])) 
str(target) 
# int [1:2, 1:6, 1:6] 15 40 65 90 115 140 165 190 215 240 ... 

Затем я проверил, что первый срез был таким же, как один результат имени я получил в начале:

target[1,,] == apply(ex_array[dimnames(ex_array)[[1]] == "10",,], 2:3, sum) 
    Col3 
Col2 1 2 3 4 5 6 
    1 TRUE TRUE TRUE TRUE TRUE TRUE 
    2 TRUE TRUE TRUE TRUE TRUE TRUE 
    3 TRUE TRUE TRUE TRUE TRUE TRUE 
    4 TRUE TRUE TRUE TRUE TRUE TRUE 
    5 TRUE TRUE TRUE TRUE TRUE TRUE 
    6 TRUE TRUE TRUE TRUE TRUE TRUE 
Смежные вопросы