6
votes

Using MATLAB, I have an array of values of size 8 rows x N columns. I need to create a matrix of the same size, that counts maximum values in each column and puts 1 in the cell that contains maximum value, and 0 elsewhere.

A little example. Lets assume we have an array of values D:

    D =
      0.0088358   0.0040346   0.40276     0.0053221
      0.017503    0.011966    0.015095    0.017383
      0.14337     0.38608     0.16509     0.15763
      0.27546     0.25433     0.2764      0.28442
      0.01629     0.0060465   0.0082339   0.0099775
      0.034521    0.01196     0.016289    0.021012
      0.12632     0.13339     0.11113     0.10288
      0.3777      0.19219     0.005005    0.40137

Then, the output matrix for such matrix D would be:

    0    0    1    0
    0    0    0    0
    0    1    0    0
    0    0    0    0
    0    0    0    0
    0    0    0    0
    0    0    0    0
    1    0    0    1

Is there a way to do it without catching vector of indices from max function and then putting ones in the right place using for loop?

3
You could do this in Python in no time ;)Hamish Grubijan
unfortunately I need to use Matlab :)Gacek
Out of curiosity, how would you want to handle the case where there are two or more values that equal the maximum in a column?gnovice
There always must be only one "1" in each column. This matrix D contains coefficients of credibility for some competitive algorithms, and there should be always only one selected. So if there are two or more equal values, algorithm must always select only one, no matter which.Gacek

3 Answers

7
votes

There are probably better ways to do it, my first approach is:

D          = rand(8,4)

[val, sub] = max(D)    
ind        = sub2ind( size(D), sub, 1:4 )

res        = false( size(D) )
res( ind ) = true
8
votes

A one-line answer:

M = D==repmat(max(D),size(D,1),1)

or more elegantly:

M = bsxfun(@eq, D, max(D))

Update:

According to the comments, if you want to be on the safe side and catch the accidental non-unique maximums, add the following statement:

M( cumsum(M)>1 ) = false

which will ensure that in the case of multiple maximums, only the first to occur has a corresponding one in the output matrix (this is equivalent to the behavior of the max() function's returned index).

1
votes

I have written an extension to the original problem that can handle arbitrary multidimension array and search for maximum along any specified dimension.

I used it to solve for the Nash equilibrium in game theory. Hope others will find it helpful.

A = rand([3 3 2]);
i = 1; % specify the dimension of A through which we find the maximum

% the following codes find the maximum number of each column of A
% and create a matrix M of the same size with A
% which puts 1 in the cell that contains maximum value, and 0 elsewhere.

[Amax pos] = max(A, [], i);
% pos is a now 1x3x3 matrix (the ith dimension is "shrinked" by the max function)

sub = cell(1, ndims(A));
[sub{:}] = ind2sub(size(pos), (1:length(pos(:)))');
sub{i} = pos(:);

ind = sub2ind(size(A), sub{:});
M = false(size(A));
M(ind) = true;

Example:

A(:,:,1) =

0.0292    0.4886    0.4588
0.9289    0.5785    0.9631
0.7303    0.2373    0.5468

A(:,:,2) =

0.5211    0.6241    0.3674
0.2316    0.6791    0.9880
0.4889    0.3955    0.0377

M(:,:,1) =

 0     0     0
 1     1     1
 0     0     0

M(:,:,2) =

 1     0     0
 0     1     1
 0     0     0