Under-appreciated accumarray
The MATLAB function accumarray seems to be under-appreciated. accumarray allows you to aggregate items in an array in the way that you specify.
Contents
Newsgroup Statistics
Since accumarray has been in MATLAB (7.0, R14), there have been over 100 threads in the MATLAB newsgroup where accumarray arose as a solution.
Recent Questions
One of the more recent threads asks how to aggregate values in one list based on another list. Suppose the lists are
group = [1 2 2 2 3 3]' data = [6 43 3 4 2 5]'
group = 1 2 2 2 3 3 data = 6 43 3 4 2 5
and the goal is to sum the data in each group. Let's first create the first input argument. accumarray wants the an array of subscripts of the data pertaining to which output value the data belongs to. Since we're just producing a column vector with 3 values, we just append a column of ones to the group vector.
indices = [group ones(size(group))]
indices = 1 1 2 1 2 1 2 1 3 1 3 1
Next We Accumulate
Since the default function for accumulation is sum, we can use the simplest form of accumarray to get the desired results.
sums = accumarray(indices, data)
sums = 6 50 7
Another Way to Accumulate
We can instead accumulate the results by adding 2 input arguments to the function call. These are the a size vector for the output array and a function handle specifying the accumulating function.
sums1 = accumarray(indices, data, [numel(unique(group)) 1], @sum)
sums1 = 6 50 7
It's easy to see that the results from the two function calls are the same.
isequal(sums, sums1)
ans = 1
Other Accumulation Functions
Sometimes, summing the results isn't what I'm looking for. Having puzzled out the 4 input call syntax, I can now simply replace the accumulation function. To find the maximum values in each group, I use this code.
maxData = accumarray(indices, data, [numel(unique(group)) 1], @max)
maxData = 6 43 5
maxData = accumarray(indices, data, [numel(unique(group)) 1], ...
@(x)~any(isfinite(x)))
maxData = 0 0 0
data(end) = Inf
maxData = accumarray(indices, data, [numel(unique(group)) 1], ...
@(x)~any(isfinite(x)))
data = 6 43 3 4 2 Inf maxData = 0 0 0
maxData = accumarray(indices, data, [numel(unique(group)) 1], ...
@(x)all(isfinite(x)))
maxData = 1 1 0
Derivative Work
John D'Errico made a more general function consolidator, found on the MathWorks File Exchange to allow you to do some extra aggregation. For example, consolidator allows the aggregation of elements when they are within a specified tolerance and not just identical.
Do You accum?
Some other obvious accumulation functions you might use include sum, max, min, prod. What functions do you use in situations when you aggregate with accumarray?