Take the product of rows in a matrix by group in R

Viewed 77

I'm looking for a way to do essentially what the rowsum function does, except take the product instead of the sum.

Let's say I have the matrix a and a vector of grouping IDs group:

a <- matrix(seq(12), ncol = 2)
group <- c(1, 1, 2, 2, 3, 3)

I can get the sums of each row by group using rowsum(a, group):

rowsum(a, group)
  [,1] [,2]
1    3   15
2    7   19
3   11   23

How could I get the product of each row by group, which would give:

  [,1] [,2]
1    2   56
2   12   90 
3   30  132
4 Answers

For values of a > 0, you could use

exp(rowsum(log(a), group))

#>    [,1] [,2]
#> 1    2   56
#> 2   12   90
#> 3   30  132

This is solution based on

a * b = exp(log(a * b)) = exp(log(a) + log(b))

You can try apply + tapply + prod

> apply(a, 2, tapply, group, prod)
  [,1] [,2]
1    2   56
2   12   90
3   30  132

In base R, aggregate should work as well

aggregate(a, list(group), FUN = prod)[-1]
  V1  V2
1  2  56
2 12  90
3 30 132

Or another option is fprod from collapse

library(collapse)
fprod(a, g = group)
  [,1] [,2]
1    2   56
2   12   90
3   30  132

I don't get the same results doing the product of the rows

a <- matrix(seq(12), ncol = 2)
group <- c(1, 1, 2, 2, 3, 3)

rowsum(a, group)
#>   [,1] [,2]
#> 1    3   15
#> 2    7   19
#> 3   11   23

matrixStats::rowProds(a,group)
#> [1]  7  7 16 16 27 27

Created on 2021-08-10 by the reprex package (v2.0.1)

Related