2

Lets say I have a 4 dimensional matrix, from which I would like to retrieve the maximum values over the 2nd and 3rd dimension.

A = rand(4, 4, 4, 4);
[max_2, in_2] = max(A, [], 2);
[max_3, in_3] = max(max_2, [], 3);

How could I use ind_2 and ind_3 to obtain a logical 4 dimensional matrix, where a 1 entry means this entry is maximum in the 2nd and 3rd dimension?

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
hasdrubal
  • 1,024
  • 14
  • 30

2 Answers2

3

I would use this approach:

A = rand(4, 4, 4, 4); % example data
B = permute(A, [1 4 2 3]); % permute dims 2 and 3 to the end
B = reshape(B, size(A,1), size(A,4), []); % collapse last two dims
C = bsxfun(@eq, B, max(B, [], 3)); % maximize over collapsed last dim
C = reshape(C, size(A,1), size(A,4), size(A,2), size(A,3)); % expand dims back
C = permute(C, [1 3 4 2]); % permute dims back. This is the final result
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Very nice approach. However, If there are multiple elements in A that have the maximum value in the 2nd or 3rd dimension, I would like only the first (a.k.a. the value of index in_2 and in_3) to be 1. the rest must be 0. – hasdrubal Oct 03 '17 at 10:08
  • @user1111652 Thanks. Pity that your question didn't specify that – Luis Mendo Oct 03 '17 at 12:07
1

Here's an approach working with linear indices and uses argmax indices from max function, so it would only consider the first argmax in case of ties for the max value -

% Get size parameters
[m,n,p,q] = size(A);

% Reshape to merge second and third dims
[~, in_23] = max(reshape(A,m,[],q), [], 2);

% Get linear indices equivalent that could be mapped onto output array
idx1 = reshape(in_23,m,q);
idx2 = bsxfun(@plus,(1:m)', m*n*p*(0:q-1)) + (idx1-1)*m;

% Initialize output array an assign 1s at linear indices from idx2
out = false(m,n,p,q);
out(idx2) = 1;

Explanation with a sample

1) Input array :

>> A
A(:,:,1,1) =
     9     8
     9     1
A(:,:,2,1) =
     2     9
     8     1
A(:,:,1,2) =
     1     7
     8     1
A(:,:,2,2) =
     8     5
     9     7

2) Reshape array for a better visualization :

>> reshape(A,m,[],q)
ans(:,:,1) =
     9     8     2     9
     9     1     8     1
ans(:,:,2) =
     1     7     8     5
     8     1     9     7

3) The question is to take max value from each of the rows. For that, we had idx2 as the linear indices :

>> idx2
idx2 =
     1    13
     2    14

Looking back at the reshape version, thus we chose (bracketed ones) -

>> reshape(A,m,[],q)
ans(:,:,1) =
    [9]     8     2     9
    [9]     1     8     1
ans(:,:,2) =
     1     7     [8]     5
     8     1     [9]     7

So, looking closely, we see that for the first row, we had two 9s, but we are choosing the first one only.

4) Finally, we are assigning these into the output array initialized as logical zeros :

>> out
out(:,:,1,1) =
     1     0
     1     0
out(:,:,2,1) =
     0     0
     0     0
out(:,:,1,2) =
     0     0
     0     0
out(:,:,2,2) =
     1     0
     1     0
Divakar
  • 218,885
  • 19
  • 262
  • 358