2016-05-02 87 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)) 

現在我想基於第一維的名稱來聚合這個數組。該維度有兩個不同的名稱(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 X你數組,然後要轉,所以在「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