jonas345
jonas345

Reputation: 71

Sum of groups of four in a matrix

I have the following matrix: first column are the values of 1 to 5, second column is 1 to 20, and the third column are random values.

1   1   2545
1   2   0
1   3   0
1   4   0
2   5   0
2   6   0
2   7   231
2   8   54587
3   9   41
3   10  1111
3   11  0
3   12  1213
4   13  0
4   14  0
4   15  0
4   16  0
5   17  898
5   18  6887
5   19  522
5   20  23    

What I am trying to do is to get the sum in groups of four when all values are different of zero. As an example, in the matrix the output I want is:

1   NaN
2   NaN
3   NaN
4   NaN
5   8330

Upvotes: 3

Views: 85

Answers (1)

rayryeng
rayryeng

Reputation: 104504

Assuming that the first column delineates what values in the third column belong to what group, the easiest would be to change all values that are zero to NaN, then use accumarray to sum all of the values that belong to each group. This is crucial because as soon as you sum over a matrix / array and any value is NaN, the result will be NaN. This is nice because if you sum over each group, you will get a NaN result if at least one of the values in the group was equal to 0 before the change.

I'm going to assume that your matrix is stored in X like so:

X = [1   1   2545
1   2   0
1   3   0
1   4   0
2   5   0
2   6   0
2   7   231
2   8   54587
3   9   41
3   10  1111
3   11  0
3   12  1213
4   13  0
4   14  0
4   15  0
4   16  0
5   17  898
5   18  6887
5   19  522
5   20  23 ];

Make a copy of the third column, and let's do some magic:

col = X(:,3);
col(col == 0) = NaN;
out = accumarray(X(:,1), col);

We thus get:

out =

         NaN
         NaN
         NaN
         NaN
        8330

The nice thing about this approach is that the group ID for each value in your matrix doesn't have to be in order as you have placed in your post.


If however your matrix is guaranteed to have the order where each group consists of consecutive 4-tuples of elements, you can do the same thing with the NaN assignment, but you can avoid using accumarray and reshape the third column into a matrix of four rows then sum over each row individually:

col = X(:,3);
col(col == 0) = NaN;
out = sum(reshape(col, 4, []), 1);

Upvotes: 8

Related Questions