MATLAB: Get indices from accumarray

accumarrayindexingMATLABvectorization

All, in a previous question ( here ) I asked what the best way was to form a matrix from a given set of indices with data assuming you know the size of the resulting matrix (also assuming that you have multiple data points for each index). The best answer was most definitely to use accumarray and it does exactly what I want. I now have another issue however. Say I have an index vector and two different data vectors that correspond to the index vector:
ind = [ 1, 2, 4, 2, 5, 6, 4, 4, 9];
data1 = [32, 14, 36, 45, 3, 1, 78, 90, 69];
data2 = [1, .5, .7, .2, 1, 1, .9, .2, .6];
Now I want to form 2 3×3 matrices from the ind/data pairs. For the first one I want to store the maximum value at each index.
mat1 = reshape(accumarray(ind,data1,[9,1],@max,0),[3,3]);
mat1 = [32,90, 0;
45, 3, 0;
0, 1,69]
For the second matix I want to store the value from data2 that corresponds to the maximum value from before. I.E. I want mat2 to look like
mat2 = [ 1,.2, 0;
.2, 1, 0;
0, 1,.6]
What is the most efficient way to do this (note that in actuality I am working with matrices that are size 600×600 or so and thus I don't really want to have to loop through each value if at all possible. I have a couple ideas about using some logical checks with bsxfun or possibly creating my own anonymous function to use in accumarray (instead of max) but I feel like those are not the ideal solutions and will they will get pretty messy.
Thanks in advance.
EDIT: Additional information
Here is one of the ideas I have that is not entirely messy, but I do have some worries about it I will point out in a second.
[data2ind,mat2ind] = find(bsxfun(@eq,data1',mat1(:)'));
mat2 = zeros(size(mat1));
mat2(mat2ind) = data2(data2ind);
So this works for the given example, but I run into an issue when mat1 has repeated values. (for example say data1 = [32, 14, 36, 32, 3, 1, 78, 90, 69]; then this won't work as is since there will be multiple places where data1=mat1). Anyway I just wanted to show where I was at right now.

Best Answer

The fastest that I could come up with is to avoid accumarray and stick with loops only... about ten times faster on my computer! Note mat is renamed tam (so that I could run both answers in a timing comparison):
tam1 = zeros(3);
tam2 = zeros(3);
for z = unique(ind)
ida = ind==z;
[tam1(z),idz] = max(data1(ida));
tmp = data2(ida);
tam2(z) = tmp(idz);
end
and the outputs are:
>> tam1
tam1 =
32 90 0
45 3 0
0 1 69
>> tam2
tam2 =
1.0000 0.2000 0
0.2000 1.0000 0
0 1.0000 0.6000
And in case you are wondering, for 10000 iterations:
Elapsed time is 6.444340 seconds. % my first answer
Elapsed time is 0.702650 seconds. % this answer