Any way for matlab to sum an array according to sp

2019-06-24 19:01发布

问题:

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!

回答1:

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.')).';


回答2:

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));
    


回答3:

Here is a solution using sort and cumsum:

[s,I]=sort(A);
c=cumsum(B(I));
k= [s(1:end-1)~=s(2:end) true];
sums = diff([0 c(k)])
bins = s(k)