tags:

views:

562

answers:

3

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?

+5  A: 

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
Mikhail
Works pretty like a charm. Thanks, Mikhail!
Gacek
I guess Matlab is also easy.
Hamish Grubijan
+1: This is the solution for the case when you just want to find the *first* occurrence of a maximum value in a column. To find *every* value equal to the maximum for each column, Amro's solution is best.
gnovice
I see. Fortunately, there is always only one max value and in fact, there should be only one "1" in each column. In other case my algorithm would crash. So, a little by accident, this solution is the best for my case
Gacek
+6  A: 

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).

Amro
+1: This was the answer I was thinking of when I asked if the OP wanted to count repeated maxima. This will mark a "1" in *every* place in a column where a value equals the maxima for that column. Mikhail's solution will find just the first occurrence.
gnovice
I guess the OP now can pick the adequate solution.. good catch though (the truth is I was just thinking of writing shorter code!)
Amro
Thanks, I forgot about the case of more than one max value. In fact, it is almost impossible to occur in my algorithm, but... Well, as I commented in other responses, I must select always only one value, so the other solution is better.
Gacek
I updated my answer to deal with that case
Amro
A: 

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
desktable
Example:A(:,:,1) = 0.0292 0.4886 0.4588 0.9289 0.5785 0.9631 0.7303 0.2373 0.5468A(:,:,2) = 0.5211 0.6241 0.3674 0.2316 0.6791 0.9880 0.4889 0.3955 0.0377M(:,:,1) = 0 0 0 1 1 1 0 0 0M(:,:,2) = 1 0 0 0 1 1 0 0 0
desktable

related questions