R sum rows of matrix by column name

Question

This seems like it should be easy but I can't figure it out. I would like to sum all of the columns of my matrix that have the same name. So, in the example below, I would like to end up with another matrix with only three columns.

set.seed(4)
z<-matrix(sample(1:10,20, replace=T), nrow=4)
colnames(z)<-c("a","c","b","a","b")
z
     a  c  b  a  b
[1,] 6  9 10  2 10
[2,] 1  3  1 10  6
[3,] 3  8  8  5 10
[4,] 3 10  3  5  8

should yield:

     a  c  b
[1,] 8  9 20
[2,] 11  3  7
[3,] 8  8  18
[4,] 8 10  11

I tried:

z<-aggregate(colnames(z), data=z, sum)

but it did not work. I would prefer to use base R if possible.


Show source
| R   | matrix   2016-12-28 00:12 4 Answers

Answers ( 4 )

  1. 2016-12-28 00:12

    Try this:

    sapply(unique(colnames(z)), function(x) rowSums(z[, colnames(z)==x, drop=FALSE]))
    
  2. 2016-12-28 00:12

    You can use rowsum with the column names as group variable:

    t(rowsum(t(z), colnames(z)))
    
    #      a  b  c
    #[1,]  8 20  9
    #[2,] 11  7  3
    #[3,]  8 18  8
    #[4,]  8 11 10
    
  3. 2016-12-28 03:12

    Here is an option using xtabs

    library(reshape2)
    xtabs(value~Var1 +Var2, melt(z))
    #    Var2
    #Var1  a  c  b
    #   1  8  9 20
    #   2 11  3  7
    #   3  8  8 18
    #   4  8 10 11
    

    Or with tapply

    tapply(z, list(row(z), colnames(z)[col(z)]), FUN = sum)
    #    a  b  c
    # 1  8 20  9
    # 2 11  7  3
    #3  8 18  8
    #4  8 11 10
    
  4. 2016-12-28 11:12

    This will also do.

    set.seed(4)
    z<-matrix(sample(1:10,20, replace=T), nrow=4)
    colnames(z)<-c("a","c","b","a","b")
    z <- as.data.table(z)
    z[,id:=.I]
    z <- melt(z,id.vars="id")
    z[,sum:=sum(value),by=.(variable,id)]
    z[,value:=NULL]
    z <- dcast.data.table(z, id~variable,value.var = "sum", fun.aggregate = max)
    z[,id:=NULL]
    

    Resulting in

        a  c  b
    1:  8  9 20
    2: 11  3  7
    3:  8  8 18
    4:  8 10 11
    
◀ Go back