MATLAB's accumarray is unbelievably powerful in many applications. My issue, is that my accumarray function to apply on my inputs has three outputs, and accumarray can only handle scalar outputs. For example, I'd like to do something like this:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
accumarray(subs, vals, [], @(x)[min(x),mean(x),max(x)],0)
and have accumarray return:
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
I suppose I could just run accumarray three times, but my function is slow, and running accumarray once would be vastly faster than running it three times. Am I just hosed here?
You can cheat make the anonymous function output a cell array instead of a single value. This way,
accumarraywill give you a cell array of matrices. You can then concatenate all of the matrices to a single matrix when you're done. Take note that your proposed anonymous function has themin,maxandmeanas a row vector but your expected result is a column vector. Therefore I've transposed this inside your anonymous function.The gotcha we have to take into account is the fill value. The fill value you specified needs to be a scalar. Therefore, you can cheat by leaving this out, but then your output will now contain empty matrices in the cell instead of the row of the result being filled with 0. A way around this is to find all cells that are empty, replace them with a row of zeros, then piece it all together when you're done. To figure out which rows of the
accumarrayoutput are going to be empty, you can usecellfuncombined withisemptyso we can see which elements in the result are empty. A neater way to do this would be to first pre-allocate a matrix ofzerosthen only populate the rows that correspond to the non-empty locations in the output ofaccumarrayto finish it off:Take note of the use of
catwhich is concatenating matrices together in a specified dimension. Doingout{:}produces what is known as a comma-separated list so it is equivalent to taking each column of theaccumarrayoutput and putting them as individual arguments intocatso that we would eventually piece all of the columns together into a single matrix, but I'm slicing into the output in such a way where we're only populating those locations that were not empty.With your test inputs, I match what you get:
However, if I can be honest - If you know for sure that you're going to only have three values to bin into
accumarray, it may be faster to simply call it three times then concatenate everything when you're done. I would argue that it's more readable and it makes it very clear what you're doing. Doing it the way I did with the cell array above requires that you really know how MATLAB works.