【问题标题】:aggregate a matrix (or data.frame) by column name groups in R按 R 中的列名组聚合矩阵(或 data.frame)
【发布时间】:2014-12-29 14:18:48
【问题描述】:

我有一个大约 3000 列 x 3000 行的大矩阵。我想汇总(计算平均值)按每一行的列名分组。每一列的命名都与此方法类似...(并以随机顺序)

 Tree Tree House House Tree Car Car House

我需要数据结果(每行的平均值聚合)具有以下列:

  Tree House Car
  • 棘手的部分(至少对我而言)是我不知道所有列名,而且它们都是随机排列的!

【问题讨论】:

    标签: r aggregate mean


    【解决方案1】:

    你可以试试

    res1 <- vapply(unique(colnames(m1)), function(x) 
          rowMeans(m1[,colnames(m1)== x,drop=FALSE], na.rm=TRUE),
                                 numeric(nrow(m1)) )
    

    或者

    res2 <-  sapply(unique(colnames(m1)), function(x) 
           rowMeans(m1[,colnames(m1)== x,drop=FALSE], na.rm=TRUE) )
    
    identical(res1,res2)
    #[1] TRUE
    

    另一种选择可能是重新整形为长格式,然后进行聚合

     library(data.table)
     res3 <-dcast.data.table(setDT(melt(m1)), Var1~Var2, fun=mean)[,Var1:= NULL]
     identical(res1, as.matrix(res3))
     [1] TRUE
    

    基准测试

    对于 3000*3000 矩阵,前两种方法似乎稍微快一些

    set.seed(24)
    m1 <- matrix(sample(0:40, 3000*3000, replace=TRUE), 
       ncol=3000, dimnames=list(NULL, sample(c('Tree', 'House', 'Car'),
        3000,replace=TRUE)))
    
    library(microbenchmark)
    
    f1 <-function() {vapply(unique(colnames(m1)), function(x) 
         rowMeans(m1[,colnames(m1)== x,drop=FALSE], na.rm=TRUE),
                               numeric(nrow(m1)) )}
    f2 <- function() {sapply(unique(colnames(m1)), function(x) 
           rowMeans(m1[,colnames(m1)== x,drop=FALSE], na.rm=TRUE) )}
    
    f3 <- function() {dcast.data.table(setDT(melt(m1)), Var1~Var2, fun=mean)[,
                Var1:= NULL]}
    
    microbenchmark(f1(), f2(), f3(), unit="relative", times=10L)
    #   Unit: relative
    # expr      min       lq     mean   median       uq      max neval
    # f1() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    10
    # f2() 1.026208 1.027723 1.037593 1.034516 1.028847 1.079004    10
    # f3() 4.529037 4.567816 4.834498 4.855776 4.930984 5.529531    10
    

    数据

     set.seed(24)
     m1 <- matrix(sample(0:40, 10*40, replace=TRUE), ncol=10, 
         dimnames=list(NULL, sample(c("Tree", "House", "Car"), 10, replace=TRUE)))
    

    【讨论】:

      【解决方案2】:

      我想出了自己的解决方案。我首先只是转置矩阵(称为 test_mean),使列变为行,然后:

      # removing numbers from rownames
      rownames(test_mean)<-gsub("[0-9.]","",rownames(test_mean))
      
      
      #aggregate by rownames
      test_mean<-aggregate(test_mean, by=list(rownames(test_mean)), FUN=mean)
      

      【讨论】:

        【解决方案3】:

        matrixStats:rowMeans2 在 data.table 的帮助下,为了胜利!

        将其添加到来自@akrun 的基准测试中,我们得到:

        f4<- function() {
          ucn<-unique(colnames(m1))
          as.matrix(setnames(setDF(lapply(ucn, function(n) rowMeans2(m1,cols=colnames(m1)==n)))
                            ,ucn))
          }
        
        > all.equal(f4(),f1())
        [1] TRUE
        
        > microbenchmark(f1(), f2(), f3(), f4(), unit="relative", times=10L)
        Unit: relative
         expr       min        lq      mean    median        uq       max neval cld
         f1()  1.837496  1.841282  1.823375  1.834471  1.818822  1.749826    10  b 
         f2()  1.760133  1.825352  1.817355  1.826257  1.838439  1.793824    10  b 
         f3() 15.451106 15.606912 15.847117 15.586192 16.626629 16.104648    10   c
         f4()  1.000000  1.000000  1.000000  1.000000  1.000000  1.000000    10 a  
        

        【讨论】:

          猜你喜欢
          • 2012-02-03
          • 2017-04-22
          • 1970-01-01
          • 2017-12-22
          • 2011-12-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多