The easiest way to describe this is via example:
data = [1, 5, 3, 6, 10];
indices = [1, 2, 2, 2, 4];
result = zeroes(1, 5);
I want result(1)
to be the sum of all the elements in data
whose index is 1
, result(2)
to be the sum of all the elements in data
whose index is 2
, etc.
This works but is really slow when applied (changing 5
to 65535
) to 64K element vectors:
result = result + arrayfun(@(x) sum(data(index==x)), 1:5);
I think it's creating 64K vectors with 64K elements that's taking up the time. Is there a faster way to do this? Or do I need to figure out a completely different approach?
for i = [1:5]
idx = indices(i);
result(idx) = result(idx) + data(i);
endfor
But that's a very non-octave-y way to do it.
Seeing how MATLAB is very similar to Octave, I will provide an answer that was tested on MATLAB R2016b. Looking at the documentation of Octave 4.2.1 the syntax should be the same.
All you need to do is this:
result = accumarray(indices(:), data(:), [5 1]).'
Which gives:
result =
1 14 0 10 0
Reshaping to a column vector (arrayName(:)
) is necessary because of the expected inputs to accumarray
. Specifying the size as [5 1]
and then transposing the result was done to avoid some MATLAB error.
accumarray
is also described in depth in the MATLAB documentation