Reputation: 71
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
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