Loren on the Art of MATLAB

Turn ideas into MATLAB

Note

Loren on the Art of MATLAB has been archived and will not be updated.

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?




Published with MATLAB® 7.5


  • print