How to Obtain the Indeces of the Minimum Value of Each Row in a Matrix and then Apply These Indeces to a New Matrix of the Same Size

1 view (last 30 days)
Say I have the following matrices:
x = [3 4; 1 3; 2 5; 7 4];
y = [1 2; 3 4; 5 6; 7 8];
If I want the minimum values by row in x, I can use
[M I] = min(x,[],2)
to obtain
M = [3; 1; 2; 4]
I = [1; 1; 1; 2]
but I am not sure how to apply I to the y matrix to obtain
y = [1; 3; 5; 8]
I have found that
diag(y(I,:))
works, but it is not efficient and will not work on the matrix that I need to apply this to, which is size(47*10^6,3). I also tried to use the find command, but I was unable to get that to work either.

Accepted Answer

Sean de Wolski
Sean de Wolski on 25 Feb 2015
Edited: Sean de Wolski on 26 Feb 2015
Use sub2ind to build a linear index and extract with this.
The rows will be (1:size(y,1)) and the columns will be your I
doc sub2ind
Something like this (not tested)
idx = sub2ind(size(y),(1:size(y,1))',I);
ymn = y(idx)
  1 Comment
Shawn
Shawn on 25 Feb 2015
In re-writing the size of the row, you wrote a "2" instead of "1", but it works once I change that. The code I use is:
ynew = y(sub2ind(size(x),(1:size(x,1))',I))
Thanks for the help!

Sign in to comment.

More Answers (1)

Matt J
Matt J on 25 Feb 2015
Edited: Matt J on 25 Feb 2015
[m,n]=size(x);
mask=sparse(1:m, I,true,m,n);
ymin=sum(mask.*y,2)
  3 Comments
Matt J
Matt J on 25 Feb 2015
This is pretty close to what I want, but it returns a sparse logical.
I think you mean a sparse double, not a sparse logical
>> whos ymin
Name Size Bytes Class Attributes
ymin 4x1 80 double sparse
Is it possible to make this return just the vector?
The result you see is a perfectly valid vector, but if you want to see it in the full form that you are used to,
>> ymin=full(ymin)
ymin =
1
3
5
8
What is meant by true?
true() is a built in MATLAB command that returns a scalar or matrix of true logical values, see
Shawn
Shawn on 25 Feb 2015
Ah, yes, I meant sparse double. mask was the sparse logical. Simplifying it down to one line, I used:
ymin=full(sum(sparse(1:size(x,1), I, true, size(x,1), size(x,2)).*y,2))
I must say that this was a really interesting and out of the box solution. I compared the 2 solutions given and found the above nearly 4x faster for random 100,000x2 matrices, which is very important to me since my matrices are very large, but I really appreciate your help and am very impressed by this method.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!