代码之家  ›  专栏  ›  技术社区  ›  Tobias Dekker

基于维度名称聚合数组

  •  2
  • Tobias Dekker  · 技术社区  · 10 年前

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

    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的值应求和。

    有什么聪明的方法可以做到这一点吗?

    3 回复  |  直到 10 年前
        1
  •  2
  •   Frank    10 年前

    重塑2。 如果您愿意使用以下软件包,我认为reconforme2最适合这里:

    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])))
    
        2
  •  2
  •   IRTFM    10 年前

    要仅对其中一个维度名称执行此操作,可以只执行以下操作:

     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数组,则需要将其转置,因此“10”值位于第一行,“20”值位于第二行。然后,可以将这些值重铸为2 x N1 x N2数组。可以将其视为首先在适当的切片坐标中放置“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
    
        3
  •  1
  •   GKi    4 年前

    tapply 可以在内部使用 apply 基于维度名称聚合数组 .

    . <- apply(ex_array, 2:3, tapply, dimnames(ex_array)[[1]], sum)
    str(.)
    # 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"
    #  ..$ Col2: chr [1:10] "1" "2" "3" "4" ...
    #  ..$ Col3: chr [1:10] "1" "2" "3" "4" ...