how to use output indexes from the MAX function

2 ビュー (過去 30 日間)
Raptrick
Raptrick 2011 年 12 月 10 日
Hi all,
I want to find the indexes of the maximum and the second maximum in 3D array for a certain dimension. My strategy is to use the MAX function for finding the indexes of the first maximum. Use these indexes to make the value of the 3D array –Inf and call again the MAX function in order to find the indexes of the second maximum of the 3D array
My question is how to make optimal use of the returned indexes from the MAX function (without for loops).
cube1 = 10*rand([5 6 7]); %create 3D array
cube2 = cube1; %make copy for com parison
[dummy i1st] = max(cube1,[],3); %find first max across 3th dimension
cube1(i1st)=-inf; % this wont work
% for loop does work but is not elegant, require recoding when dimension in changed
for r=1:size(i1st,1)
for c=1:size(i1st,2)
cube1(r,c,i1st(r,c)) = -inf;
end
end
[dummy i2nd] = max(cube1,[],3); %find second max across 3th dimension
Does anyone has some ideas how to get rid of the for loop?
Patrick
  3 件のコメント
Andrei Bobrov
Andrei Bobrov 2011 年 12 月 12 日
[v,idx] = sort(cube1,3);
dummy = v(:,:,end-1) ;
i2nd = idx(:,:,end-1);
Andrei Bobrov
Andrei Bobrov 2011 年 12 月 12 日
[~,i3] = max(cube1,[],3)
M1 = cube1;
s = size(cube1);
M1((i3-1).*prod(s(1:2))+reshape(1:prod(s(1:2)),s(1),[])) = -inf
[dummy,i2nd] = max(M1,[],3);

サインインしてコメントする。

採用された回答

Sven
Sven 2011 年 12 月 11 日
Hi Patrick, I think this is what you want to do:
arrSz = [5 6 7]; % Size of matrix
cube1 = 10*rand(arrSz); % Create the matrix
[vals1, idxs1] = max(cube1,[],3); % find first max across 3th dimension
% Make a 3D mask corresponding to indices in idxs1
idxsMask = bsxfun(@eq,reshape(1:arrSz(3), 1,1,[]), idxs1);
cube1(idxsMask) = -inf; % Set first max vals to -inf
[vals2, idxs2] = max(cube1,[],3); % find second max across 3th dimension
The trick here is the bsxfun() call. I make a set of indices along the 3rd dimension, then bsxfun does its magic asking if the 2D matrix idxs1 matches that array. bsxfun() is a strange function if you haven't seen it before, but once you understand what it does it can be very useful. And very efficient - much faster than the loop.
Walter's question is a valid one... what if the max value isn't unique along the 3rd dimension? Should your second call to max() return the next index that had the same value as the first call? Or should the first call turn all elements that had the max value to -inf?
If you want to do this second way, simply replace the idxsMask line above with the following:
idxsMask = bsxfun(@eq,vals1,cube1);

その他の回答 (1 件)

Raptrick
Raptrick 2011 年 12 月 12 日
Thanks Sven,
This works! The BSXFUN is new for me. I will investigate the capabilities of this function. Good remark from Walter about the uniqueness of the max. For my application it is preferable to find one max at a time, not multiple values. For the sake of fun I generalize this piece of code:
dim=3; % Operates along the dimension dim
[vals1,idxs1] = max(cube1,[],dim); % Find first max along dimension dim
% Make a 3D mask corresponding to indices in idxs1
order = 1:numel(size(cube1));
order([1,dim])=order([dim,1]);
idxsMask = bsxfun(@eq,permute([1:arrSz(dim)]',order), idxs1);
cube1(idxsMask) = -inf; % Set first max vals to -inf
Patrick

カテゴリ

Help Center および File ExchangeMatrix Indexing についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by