OK, so the subs matrix represent the rows and columns of the matrix A. (1, 1) represent the first row and first column. (3, 2) represents the 3rd row and 2nd column. If you don't get this, look at the document on ind2sub on this page. Now the vals are associated with each row in subs (e.g. the first (1, 1) associated with 101, up to (4, 1) with 106). And the values get accumulated in the groups determined by the rows of subs. Therefore, the two rows of (1, 1) have the values 101 and 104. This adds to 205, which is why A(1,1) = 205. (2, 2) are 102 and 105. Thus, A(2,2) = 207. (3,2) --> 103, A(3,2) = 103. (4,1) --> 106, A(4,1) = 106. It's pretty clear if you look at the last image on the accumarray page. https://www.mathworks.com/help/matlab/ref/accumarray.png Answer from Daniel M on mathworks.com
🌐
MathWorks
mathworks.com › matlab › data import and analysis › data preprocessing
accumarray - Accumulate vector elements - MATLAB
This MATLAB function sums groups of data by accumulating elements of a vector data according to the groups specified in ind.
Top answer
1 of 2
1
OK, so the subs matrix represent the rows and columns of the matrix A. (1, 1) represent the first row and first column. (3, 2) represents the 3rd row and 2nd column. If you don't get this, look at the document on ind2sub on this page. Now the vals are associated with each row in subs (e.g. the first (1, 1) associated with 101, up to (4, 1) with 106). And the values get accumulated in the groups determined by the rows of subs. Therefore, the two rows of (1, 1) have the values 101 and 104. This adds to 205, which is why A(1,1) = 205. (2, 2) are 102 and 105. Thus, A(2,2) = 207. (3,2) --> 103, A(3,2) = 103. (4,1) --> 106, A(4,1) = 106. It's pretty clear if you look at the last image on the accumarray page. https://www.mathworks.com/help/matlab/ref/accumarray.png
2 of 2
0
For the simplest case shown in the first example as well as the image at the end of the function page. The acumarray function takes in two inputs for example vectors, ind and data. These must be equal lengths and thus the ind vector serves to index the data vector. The function then applies an input function, argument number 4 (fun), or by default applies the sum function to the data vector. The function is applied according to the unique indexes present in ind corresponding to values in data. Thus for the first example with inputs "data = [1 2 3 4 5 6]" and "ind = [1 3 4 2 4 1]" acumarray sums the '1' indexes 1+6, '2' indexes 4, '3' indexes 2, and '4' indexes 3+5. The result is thus "ans = [7 4 2 8]". Very confusing documentation for this function in my opinion especially given the lack of detail in the "More About" section.
Discussions

how to use accumarray over a matrix avoiding a loop?
Hi, I want to sum elements of a matrix according to an index. If instead of the matrix I had a vector, I could use accumarray. However, accumarray does not accept matrices as second argument. An... More on mathworks.com
🌐 mathworks.com
4
0
February 12, 2013
Understanding accumarray in Matlab - Stack Overflow
As the documentation say, "If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data." So, to get predictable behavior out of accumarray, the subs have to be sorted. More on stackoverflow.com
🌐 stackoverflow.com
How to make it accumarray?
How to make it accumarray?. Learn more about matlab MATLAB More on mathworks.com
🌐 mathworks.com
0
0
January 5, 2022
Do not understand 'accumarray' command in Maltab
Hi everybody, I think you know about command "accumarray" in Matlab. That command is not supported in HDL Coder( convert code Matlab to VHDL). So, I try to write down another function which is ... More on mathworks.com
🌐 mathworks.com
2
0
August 16, 2016
🌐
MathWorks
mathworks.com › matlabcentral › answers › 163237-how-to-use-accumarray
How to use accumarray? - MATLAB Answers - MATLAB Central
November 18, 2014 - meandailyzone1 = accumarray(subs, m(:, 7), [], @mean) You do the same for the other criteria, varying the columns you pass to unique · Sign in to comment. Kelly Kearney on 18 Nov 2014 · Open in MATLAB Online · 0 votes · Share · Translate · Share a link to this answer ·
🌐
MathWorks
blogs.mathworks.com › loren › 2008 › 02 › 20 › under-appreciated-accumarray
Under-appreciated accumarray » Loren on the Art of MATLAB - MATLAB & Simulink
February 20, 2008 - 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.
🌐
MATLAB
matlab.izmiran.ru › help › techdoc › ref › accumarray.html
accumarray (MATLAB Functions)
A = accumarray(ind, val, sz, fun, fillvalue) where val is full, fills in the values of A at unspecified indices with the value fillvalue.
🌐
Fanwang Econ
fanwangecon.github.io › M4Econ › amto › array › htmlpdfm › fs_accumarray.html
Matlab Accumarray Examples
a1 = [1,1,2,2] a1 = 1x4 1 1 2 2 a2 = [3,2,1,3] a2 = 1x4 3 2 1 3 a3 = [1,2,3,3] a3 = 1x4 1 2 3 3 a = [a1;a2;a3]'/2 a = 4x3 0.5000 1.5000 0.5000 0.5000 1.0000 1.0000 1.0000 0.5000 1.5000 1.0000 1.5000 1.5000 prob_a = zeros(size(a)) + 1/12 prob_a = 4x3 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 0.0833 [ar_idx_full, ~, ar_idx_of_unique] = unique(a) ar_idx_full = 3x1 0.5000 1.0000 1.5000 ar_idx_of_unique = 12x1 1 1 2 2 3 2 1 3 1 2 mt_idx_of_unique = reshape(ar_idx_of_unique, size(a)) mt_idx_of_unique = 4x3 1 3 1 1 2 2 2 1 3 2 3 3 accumarray(mt_idx_of_unique(:,1), prob_a(:,1)) ans = 2x1 0.1667 0.1667 accumarray(mt_idx_of_unique(:,2), prob_a(:,2)) ans = 3x1 0.0833 0.0833 0.1667 accumarray(mt_idx_of_unique(:,3), prob_a(:,3)) ans = 3x1 0.0833 0.0833 0.1667
Find elsewhere
Top answer
1 of 2
2

I think the unexpected values are because you are expecting the values to be passed to the anonymous function in the same order as the relevant indices appears in subs.

However, the documentation for accumarray says:

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

This means that the start of subs ( 1 2; 1 2; ) can result in 102 101 or 101 102 being passed to the anonymous function (because the documentation says that fun should not depend on the order of values.

sum(diff([102 101])) is -1 which is the value written to element 1,2 in the example

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

I'm not sure why Mathworks would choose to use the diff function in an example when the result of diff is obviously dependent on the order of values passed to it.

It looks like this input value ordering is the reason for the other output values being different from your expectations.

2 of 2
1

The why is in grantnz's answer, here's how to get predictable behavior.

As the documentation say, "If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data." So, to get predictable behavior out of accumarray, the subs have to be sorted.

What that means for subscripts representing (row,column) locations in a matrix is that the elements to which the subscripts point must be ordered according to the linear index. Thus, to "sort" 2D subscripts, you need to sort the equivalent linear index. Then you need to apply that order to vals, otherwise you have scrambled your data.

val = 101:106;
subs = [1 2; 1 2; 3 1; 4 1; 4 4; 4 1];

% convert the subscripts to linear inds and sort them
inds = sub2ind([4 4],subs(:,1),subs(:,2));
[indsSorted,sortingInds] = (sort(inds));

% apply the sorting to val
valsSorted = val(sortingInds);

% convert inds back to subs
[iiS jjS] = ind2sub([4 4],indsSorted);
subsSorted = [iiS jjS];

B = accumarray(subsSorted,valsSorted,[],@(x)sum(diff(x)))

B =

     0     1     0     0
     0     0     0     0
     0     0     0     0
     2     0     0     0

At least it would see that this is what that note in the documentation is saying.

🌐
Mathengineering
mathengineering.com › sparse-and-automatic-accumulation
Sparse and Automatic Accumulation – Mathematical Engineering
Current versions of MATLAB also contain a function called accumarray that performs the accumulation trick for non-sparse matrices (and you can change the accumulation function too).
🌐
MathWorks
mathworks.com › matlabcentral › answers › 1622825-how-to-make-it-accumarray
How to make it accumarray? - MATLAB Answers - MATLAB Central
January 5, 2022 - Hi, may I ask that how to make it be accumulative array. I will be grateful that provide the idea. Thanks! %% Initialize Input K = 1*(10^-9); % Carrying Capacity of Brain Tumor C0 = 40000; % Ini...
🌐
MathWorks
mathworks.com › matlabcentral › answers › 47768-on-the-use-of-the-accumarray-function
on the use of the accumarray function - MATLAB Answers - MATLAB Central
September 10, 2012 - accumarray uses fillval to fill in elements who have no subs. You can set it using the 5th input to accumarray ... https://www.mathworks.com/matlabcentral/answers/47768-on-the-use-of-the-accumarray-function#comment_98522
🌐
Reddit
reddit.com › r/matlab › what does accumarray([1,2,3], 1) do?
r/matlab on Reddit: What does accumarray([1,2,3], 1) do?
September 12, 2022 -

I tried with different values for the second argument but it just seems as if the value for the second argument ends up in the last output. Can't make sense out of it. Can someone give me a hint?

Edit. I guess if I vary the first argument to [2, 8] i get more insight, but not sure whether its the right one. Then the output is a 2 by 8 matrix with the second argument being the entry for a_{2,8}. why would one want that? especially compared to the use as a group count function in the first example in its documentation: https://www.mathworks.com/help/matlab/ref/accumarray.html

🌐
MathWorks
mathworks.com › matlabcentral › answers › 481893-use-of-accumarray-function
Use of accumarray function - MATLAB Answers - MATLAB Central
September 24, 2019 - https://www.mathworks.com/matlabcentral/answers/481893-use-of-accumarray-function · Cancel Copy to Clipboard · Hi everybody; Please find here below my question : I have 3D available data : Xaxis : AZ, Yaxis : EL, Zaxis : Gain, whose Xaxis & Yaxis data are non regular ·
Top answer
1 of 2
9

One solution is to replicate the row indices in labels and add another column of column indices. Then you can reshape X into a column vector and apply accumarray once:

labels = [repmat(labels(:),nCols,1) ...            % Replicate the row indices
          kron(1:nCols,ones(1,numel(labels))).'];  % Create column indices
totals = accumarray(labels,X(:));  % I used "totals" instead of "means"


How it works...

A = accumarray(subs,val) for a column vector subs and vector val works by adding the number in val(i) to the total in row subs(i) in the output column vector A. However, subs can contain more than just row indices. It can contain subscript indices for multiple dimensions to assign values to in the output. This feature is what allows you to handle an input val that is a matrix instead of a vector.

First, the input for val can be reshaped into a column vector using the colon operator X(:). Next, in order to keep track of which column in the output the values in X(:) should be placed, we can modify the input subs to include an additional column index. To illustrate how this works, I'll use these sample inputs:

labels = [3; 1; 1];
X = [1 2 3; ...
     4 5 6; ...
     7 8 9];
nCols = 3

And here are what the variables in the above code end up looking like:

labels = 3 1    X(:) = 1    totals = 11 13 15
         1 1           4              0  0  0
         1 1           7              1  2  3
         3 2           2
         1 2           5
         1 2           8
         3 3           3
         1 3           6
         1 3           9

Notice, for example, that the values 1 4 7 that were originally in the first column of X will only be accumulated in the first column of the output, as denoted by the ones in the first three rows of the second column of labels. The resulting output should be the same as what you would have gotten by using the code in the question where you loop over each column to perform the accumulation.

2 of 2
1

Perhaps a more intuitive (maybe more efficient) way borrowed from MATLAB Answers (the original answer assumes column-major inputs so I transposed them):

[xx, yy] = ndgrid(labels,1:size(X, 1));
totals = accumarray([yy(:) xx(:) ], reshape(X.', 1, []));

Example:

X = [1 2 3 4; 5 6 7 8];
labels = [2; 1; 3; 1];

gives totals = [6 1 3; 14 5 7].

If you want to do this row-wise then there's no need to transpose, just:

[xx, yy] = ndgrid(labels,1:size(X, 2));
totals = accumarray([xx(:) yy(:)], X(:));