1
votes

I have a vector J which contains the row index of a vector. I would like to do the following code in a vectorized way : I want to sum the duplicate values to the variable 'Mode' from the variable 'M'. I have size(M)=size(J). This is my attempted code:

Mode=zeros(n,1);
for i=1:length(J)
    Mode(J(i))=Mode(J(i))+M(i);
end

I have tested with

Mode(J)=M

but the problem is that there are some duplicate index value in J. How can I implement it correctly ?

1
@x1hgg1x Loops have gotten a lot faster in Matlab and I'd just leave this in a loop unless there are performance problems. - Matthew Gunn
@MatthewGunn What you mean about increasing loop speed in Matlab? is it for 2015b ? - Mikhail_Sam
@MatthewGunn The problem is that the size of J is pretty huge, and since this code is in an optimisation function I would like to improve run time. - x1hgg1x
You can use accumarray - angainor
Is Mode(J(i))=Mode(J(i))+M(i); supposed to be Mode(J(i))=Mode(J(i))+M(J(i));? - Matthew Gunn

1 Answers

3
votes

You're probably looking for accumarray.

Have a look at this example:

J = [1 2 3 5 2 3].';
M = [1 1 1 1 1 1].';
Mode = accumarray(J, M, size(J)) 

Mode =

     1
     2
     2
     0
     1
     0

From the documentation:

A = accumarray(subs,val) returns array A by accumulating elements of vector val using the subscripts subs. If subs is a column vector, then each element defines a corresponding subscript in the output, which is also a column vector. The accumarray function collects all elements of val that have identical subscripts in subs and stores their sum in the location of A corresponding to that subscript (for index i, A(i)=sum(val(subs(:)==i))). Elements of A whose subscripts do not appear in subs are equal to 0.

size(J) is used to make sure the dimension of Mode is the same as the dimension of J.


According to OP, the following code works:

A=accumarray(J,M); 
Mode(1:size(A))=A;