Construct array with accumulation

Syntax

A = accumarray(subs,val)
A = accumarray(subs,val,sz)
A = accumarray(subs,val,sz,fun)
A = accumarray(subs,val,sz,fun,fillval)
A = accumarray(subs,val,sz,fun,fillval,issparse)
A = accumarray({subs1, subs2, …}, val, …)

Description

accumarray groups elements from a data set and applies a function to each group. A = accumarray(subs,val) creates an array A by accumulating elements of the vector val using the elements of subs as indices. The position of an element in subs determines which value of vals it selects for the accumulated vector; the value of an element in subs determines the position of the accumulated vector in the output.

A = accumarray(subs,val,sz) creates an array A with size sz, where sz is a vector of positive integers. If subs is nonempty with N>1 columns, then sz must have N elements, where all(sz >= max(subs,[],1)). If subs is a nonempty column vector, then sz must be [M 1], where M >= MAX(subs). Specify sz as [] for the default behavior.

A = accumarray(subs,val,sz,fun) applies function fun to each subset of elements of val. The default accumulating function is sum. To specify another function fun, use the @ symbol (e.g., @max). The function fun must accept a column vector and return a numeric, logical, or character scalar, or a scalar cell. Return value A has the same class as the values returned by fun. Specify fun as [] for the default behavior.

A = accumarray(subs,val,sz,fun,fillval) puts the scalar value fillval in elements of A that are not referred to by any row of subs. For example, if subs is empty, then A is repmat(fillval,sz). fillval and the values returned by fun must belong to the same class. The default value of fillval is 0.

A = accumarray(subs,val,sz,fun,fillval,issparse) creates an array A that is sparse if the scalar input issparse is equal to logical 1 (i.e., true), or full if issparse is equal to logical 0 (false). A is full by default. If issparse is true, then fillval must be zero or [], and val and the output of fun must be double.

A = accumarray({subs1, subs2, …}, val, …) passes multiple subs vectors in a cell array. You can use any of the four optional inputs (sz, fun, fillval, or issparse) with this syntax.

Note If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data.

The function processes the input as follows:

1.

Find out how many unique indices there are in subs. Each unique index defines a bin in the output array. The maximum index value in subs determines the size of the output array.
2.

Find out how many times each index is repeated.

This determines how many elements of vals are going to be accumulated at each bin in the output array.
3.

Create an output array. The output array is of size max(subs) or of size sz.
4.

Accumulate the entries in vals into bins using the values of the indices in subs and apply fun to the entries in each bin.
5.

Fill the values in the output for positions not referred to by subs. Default fill value is zero; use fillval to set a different value.

Note subs should contain positive integers. subs can also be a cell vector with one or more elements, each element a vector of positive integers. All the vectors must have the same length. In this case, subs is treated as if the vectors formed columns of an index matrix.val must be a numeric, logical, or character vector with the same length as the number of rows in subs. val can also be a scalar whose value is repeated for all the rows of subs.

Examples

Example 1

Create a 5-by-1 vector and sum values for repeated 1-D subscripts:

val = 101:105;
subs = [1; 2; 4; 2; 4]
subs =
     1 
     2 
     4 
     2 
     4 

A = accumarray(subs, val)
A =
   101       % A(1) = val(1) = 101
   206       % A(2) = val(2)+val(4) = 102+104 = 206
     0       % A(3) = 0
   208       % A(4) = val(3)+val(5) = 103+105 = 208

Example 2

Create a 4-by-4 matrix and subtract values for repeated 2-D subscripts:

val = 101:106;
subs=[1 2; 1 2; 3 1; 4 1; 4 4; 4 1];
B = accumarray(subs,val,[],@(x)sum(diff(x)))

B =

     0    -1     0     0
     0     0     0     0
     0     0     0     0
     2     0     0     0

The order of the subscripts matters:

val = 101:106;
subs=[1 2; 3 1; 1 2; 4 4; 4 1; 4 1];
B1 = accumarray(subs,val,[],@(x)sum(diff(x)))

B1 =

     0    -2     0     0
     0     0     0     0
     0     0     0     0
    -1     0     0     0

Example 3

Create a 2-by-3-by-2 array and sum values for repeated 3-D subscripts:

val = 101:105;
subs = [1 1 1; 2 1 2; 2 3 2; 2 1 2; 2 3 2];

A = accumarray(subs, val)
A(:,:,1) =
   101     0     0
     0     0     0
A(:,:,2) =
     0     0     0
   206     0   208

Example 4

Create a 2-by-3-by-2 array, and sum values natively:

val = 101:105;
subs = [1 1 1; 2 1 2; 2 3 2; 2 1 2; 2 3 2];

A = accumarray(subs, int8(val), [], @(x) sum(x,'native'))
A(:,:,1) =
  101    0    0
    0    0    0
A(:,:,2) =
    0    0    0
  127    0  127

class(A)
ans =
    int8

Example 5

Pass multiple subscript arguments in a cell array.

1.

Create a 12-element vector V:

V = 101:112;

2.

Create three 12-element vectors, one for each dimension of the resulting array A. Note how the indices of these vectors determine which elements of V are accumulated in A:

      %        index 1   index 6 => V(1)+V(6) => A(1,3,1)
      %          |         |
      rowsubs = [1 3 3 2 3 1 2 2 3 3 1 2];
      colsubs = [3 4 2 1 4 3 4 2 2 4 3 4];
      pagsubs = [1 1 2 2 1 1 2 1 1 1 2 2];
      %                |
      %              index 4 => V(4) => A(2,1,2)
      %
      % A(1,3,1) = V(1) + V(6) = 101 + 106 = 207
      % A(2,1,2) = V(4) = 104

3.

Call accumarray, passing the subscript vectors in a cell array:

      A = accumarray({rowsubs colsubs pagsubs}, V)
      A(:,:,1) =
           0     0   207     0        % A(1,3,1) is 207
           0   108     0     0
           0   109     0   317
      A(:,:,2) =
           0     0   111     0
         104     0     0   219        % A(2,1,2) is 104
           0   103     0     0

Example 6

Create an array with the max function, and fill all empty elements of that array with NaN:

val = 101:105;
subs = [1 1; 2 1; 2 3; 2 1; 2 3];

A = accumarray(subs, val, [2 4], @max, NaN)
A =
   101   NaN   NaN   NaN
   104   NaN   105   NaN

Example 7

Create a sparse matrix using the prod function:

val = 101:105;
subs = [1 1; 2 1; 2 3; 2 1; 2 3];

A = accumarray(subs, val, [2 4], @prod, 0, true)
A =
   (1,1)            101
   (2,1)          10608
   (2,3)          10815

Example 8

Count the number of entries accumulated in each bin:

val = 1;
subs = [1 1; 2 1; 2 3; 2 1; 2 3];

A = accumarray(subs, val, [2 4])
A =
     1     0     0     0
     2     0     2     0

Example 9

Create a logical array that shows which bins will accumulate two or more values:

val = 101:105;
subs = [1 1; 2 1; 2 3; 2 1; 2 3];

A = accumarray(subs, val, [2 4], @(x) length(x) > 1)
A =
     0     0     0     0
     1     0     1     0

Example 10

Group values in a cell array:

val = 101:105;
subs = [1 1; 2 1; 2 3; 2 1; 2 3];

A = accumarray(subs, val, [2 4], @(x) {x})
A = 
    [       101]     []              []     []
    [2x1 double]     []    [2x1 double]     []

A{2}
ans =
   104
   102

See Also

full, sparse, sum