accumarray()'s val
argument must be a vector. In my case I need columns of a matrix to be summed (or averaged). Is there a function or a method to achieve this?
What I am doing now is in a for loop I am summing column values separately:
for iCol = 1:nCols
means(:,iCol) = accumarray(labels', X(:,iCol));
end
Perhaps a more intuitive (maybe more efficient) way borrowed from MATLAB Answers (the original answer assumes column-major inputs so I transposed them):
Example:
gives
totals = [6 1 3; 14 5 7]
.If you want to do this row-wise then there's no need to transpose, just:
One solution is to replicate the row indices in
labels
and add another column of column indices. Then you can reshapeX
into a column vector and applyaccumarray
once:How it works...
A = accumarray(subs,val)
for a column vectorsubs
and vectorval
works by adding the number inval(i)
to the total in rowsubs(i)
in the output column vectorA
. 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 inputval
that is a matrix instead of a vector.First, the input for
val
can be reshaped into a column vector using the colon operatorX(:)
. Next, in order to keep track of which column in the output the values inX(:)
should be placed, we can modify the inputsubs
to include an additional column index. To illustrate how this works, I'll use these sample inputs:And here are what the variables in the above code end up looking like:
Notice, for example, that the values
1 4 7
that were originally in the first column ofX
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 oflabels
. 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.