根据维度名称聚合数组

时间:2016-05-02 08:29:35

标签: arrays r matrix aggregate

我正在尝试以有效的方式基于维名称聚合数组。

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 个答案:

答案 0 :(得分: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 x N1 x N2阵列,然后需要对其进行转置,因此&#34; 10&#34;值是顶行和&#34; 20&#34;值是第二行。然后,这些值可以重铸为2 x N1 xN2阵列。您可以将其视为首次放置&#34; 10&#34;在适当的切片坐标中的值,然后放置&#34; 20&#34;价值坐标,等等:

 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

答案 1 :(得分: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])))