2016-05-02 15 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" 

....それは列優先順でありますし、それを書き直すためにN1がN2配列をX X 2は、あなたがして、それを転置する必要がありますので、 「10」の値は一番上の行、「20」の値は二番目の行です。これらの値は、2 x N1 xN2配列にリキャストすることができます。私は、最初のスライスと確認

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

:あなたは「20」の値COORDを配置することにより、その後、座標適切なスライスに最初の配置「10」の値としてそれを考える、というように、というようにすることができます

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 
関連する問題