Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way for matlab to sum an array according to specified bins NOT by for iteration? Best if there is buildin function for this

For example, if

A = [7,8,1,1,2,2,2]; % the bins (or subscripts)
B = [2,1,1,1,1,1,2]; % the array

then the desired function "binsum" has two outputs, one is the bins, and the other is the sum. It is just adding values in B according to subscripts in A. For example, for 2, the sum is 1 + 1 + 2 = 4, for 1 it is 1 + 1 = 2.

[bins, sums] = binsum(A,B);

bins = [1,2,7,8]
sums = [2,4,2,1]

The elements in "bins" need not be ordered but must correspond to elements in "sums". This can surely be done by "for" iterations, but "for" iteration is not desired, because there is a performance concern. It is best if there is a build in function for this.

Thanks a lot!

like image 434
Tony Avatar asked Dec 23 '22 15:12

Tony


2 Answers

This is another job for accumarray

A = [7,8,1,1,2,2,2]; % the bins (or subscripts)
B = [2,1,1,1,1,1,2]; % the array

sums = accumarray(A.', B.').';
bins = unique(A);

Results:

>> bins
bins =

   1   2   7   8

sums =

   2   4   0   0   0   0   2   1

The index in sums corresponds to the bin value, so sums(2) = 4. You can use nonzeros to remove the unused bins so that bins(n) corresponds to sums(n)

sums = nonzeros(sums).';

sums =

   2   4   2   1

or, to generate this form of sums in one line:

sums = nonzeros(accumarray(A.', B.')).';
like image 106
beaker Avatar answered Jan 13 '23 11:01

beaker


Another possibility is to use sparse and then find.

  • Assuming A contains positive integers,

    [bins, ~, sums] = find(sparse(A, 1, B));
    

    This works because sparse automatically adds values (third input) for matching positions (as defined by the first two inputs).

  • If A can contain arbitrary values, you also need a call to unique, and find can be replaced by nonzeros:

    [bins, ~, labels]= unique(A);
    sums = nonzeros(sparse(labels, 1, B));
    
like image 41
Luis Mendo Avatar answered Jan 13 '23 10:01

Luis Mendo