Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge columns based on value at index in a separate vector

Tags:

r

I have a matrix like this:

> y
     [,1] [,2] [,3] [,4]
[1,]   17   14    5    8
[2,]    7    2   17    2
[3,]   10   18    6    6
[4,]    6   11    4   11
[5,]    5    9    4    9

and a vector

> group
[1] 1 2 2 3

The group vector indicates that column 1 is in group 1, columns 2 and 3 are in group 2 and column 3 is in group 3. I want to combine columns in y (by addition) so that all the columns assigned to a particular group are added together i.e. so that I get:

     [,1] [,2] [,3]
[1,]   17   19    8
[2,]    7   19    2
[3,]   10   24    6
[4,]    6   15   11
[5,]    5   13    9

I've been messing around with subset, merge and Reduce but I'm really not getting anywhere.

like image 728
kmt Avatar asked Jun 14 '17 11:06

kmt


2 Answers

We can do

sapply(split(seq_along(group), group), function(x) rowSums(y[, x, drop = FALSE]))
#     1  2  3
#[1,] 17 19  8
#[2,]  7 19  2
#[3,] 10 24  6
#[4,]  6 15 11
#[5,]  5 13  9

Or another option is rowsum

t(rowsum(t(y), group))
#      1  2  3
#[1,] 17 19  8
#[2,]  7 19  2
#[3,] 10 24  6
#[4,]  6 15 11
#[5,]  5 13  9
like image 104
akrun Avatar answered Nov 15 '22 08:11

akrun


Here's a dplyr way:

data.frame(group = group, t(y)) %>% 
  group_by(group) %>% 
  summarise_each(funs(sum), -group) %>%
  ungroup() %>%
  select(-group) %>%
  as.matrix() %>%
  t()

Broken down, we transpose y and make it a data.frame with group as a separate column. Then we're free to take each column's group_by & sum on the group. The last four steps are about transforming the result back into your desired format.

like image 23
lebelinoz Avatar answered Nov 15 '22 08:11

lebelinoz