2016-05-02 5 views
2

Ich versuche, ein Array basierend auf dem Dimensionsnamen auf effiziente Weise zu aggregieren.Aggregieren eines Arrays basierend auf den Dimensionsnamen

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)) 

Jetzt möchte ich dieses Array auf der Grundlage der Namen der ersten Dimension aggregieren. Diese Dimension hat zwei verschiedene Namen (10 und 20). Daher sollte das neue Array die Dimension 2 mal 10 mal 10 haben. Alle Werte mit dem Dimensionsnamen 1, die 10 entsprechen, sollten addiert werden und die Werte mit Dimension 1 sollten 20 sein zusammengefasst werden.

Gibt es eine clevere Möglichkeit, dies zu tun?

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

Wenn Sie dann, dass wickeln in einem sapply Sie eine 2 x prod(N1, N2) Matrix mit den richtigen Informationen erhalten, rufen:

Antwort

2

reshape2. ich reshape2 denke, ist die beste Lösung hier, wenn Sie bereit sind, Pakete zu verwenden:

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" ... 

Ich denke, dies auch Duplikate in den anderen Dimensionen Namen zusammenbrechen würde (wenn es welche gibt).


Basis R. können Sie rowsum verwenden, aber es ist hier klobig, weil es mir meine Schaften für Matrizen

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

Als ich Durchführung dachte ich entworfen ist, dass dies wahrscheinlich aussehen würde viel kompakter, wenn es durch "reshape2" oder "splitstackshape" oder "dplyr" Funktionen gemacht wird. (Und es liefert, was ich denke, ist das richtige Ergebnis auch.) –

2

es eine der Dimensionsnamen für nur zu tun, könnte es nur sein. Ich arbeitete mit einer geschrumpften Version Ihres Beispiel-Datensatz:

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" 

.... aber es ist in der Spalte-Großauftrag und es neu zu fassen, um ein 2 x N1 N2 Array x Sie dann umsetzen müssen, so dass die "10" -Werte sind die obere Reihe und die "20" -Werte sind die zweite Reihe. Dann können diese Werte in ein 2 × N1 × N2-Array umformatiert werden. Sie können als erste Platzierung daran denken „10“ Wert in der richtigen Scheibe koordinieren, gefolgt von „20“ Wert coord platzieren, und so weiter, und so weiter:

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 ... 

ich dann überprüft, dass die erste Scheibe war die gleiche wie die einzelnen Namen Ergebnis, das ich am Anfang bekam:

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 
Verwandte Themen