Find highest/lowest value in matrix - matlab

very basic question: How can I find the highest or lowest value in a random matrix.
I know there is a possibility to say:
a = find(A>0.5)
but what I'm looking for would be more like this:
A = rand(5,5)
A =
0.9388 0.9498 0.6059 0.7447 0.2835
0.6338 0.0104 0.5179 0.8738 0.0586
0.9297 0.1678 0.9429 0.9641 0.8210
0.0629 0.7553 0.7412 0.9819 0.1795
0.3069 0.8338 0.7011 0.9186 0.0349
% find highest (or lowest) value
ans = A(19)%for the highest or A(7) %for the lowest value in this case

Have a look at the min() and max() functions. They can return both the highest/lowest value, and its index:
[B,I]=min(A(:)); %# note I fixed a bug on this line!
returns I=7 and B=A(7)=A(2,2). The expression A(:) tells MATLAB to treat A as a 1D array for now, so even though A is 5x5, it returns the linear index 7.
If you need the 2D coordinates, i.e. the "2,2" in B=A(7)=A(2,2), you can use [I,J] = ind2sub(size(A),I) which returns I=2,J=2, see here.
Update
If you need all the entries' indices which reach the minimum value, you can use find:
I = find(A==min(A(:));
I is now a vector of all of them.

For matrices you need to run the MIN and MAX functions twice since they operate column-wise, i.e. max(A) returns a vector with each element being the maximum element in the corresponding column of A.
>> A = rand(4)
A =
0.421761282626275 0.655740699156587 0.678735154857773 0.655477890177557
0.915735525189067 0.0357116785741896 0.757740130578333 0.171186687811562
0.792207329559554 0.849129305868777 0.743132468124916 0.706046088019609
0.959492426392903 0.933993247757551 0.392227019534168 0.0318328463774207
>> max(max(A))
ans =
0.959492426392903
>> min(min(A))
ans =
0.0318328463774207
Note that this only works for matrices. Higher dimensional arrays would require running MIN and MAX as many times as there are dimensions which you can get using NDIMS.

Try this out
A=magic(5)
[x,y]=find(A==max(max(A))) %index maximum of the matrix A
A_max=A(x,y)
[x1,y1]=find(A==min(max(A))) %index minimum of the matrix A
A_min=A(x1,y1)

Related

Finding minimum array of matrix with condition

I want to find the minimum of a matrix say A. I could do it in this way:
NM = find(A==min(A));
but I need the minimum array of A which for it, c(NM) is not zero. How can I put this condition on finding minimum value?
Example:
c=[0,18,9,0,100,0];
A=[1,189,125,25,7,1];
I expext it returns 5.
You can use logical indexing to find the desired elements.
find(A==min(A(c~=0)))
Explanation:
Using logical indexing you first find indices of elements of c that are nonzero.
idx1 = c~=0;
then elements of A that correspond to indices of nonzeros elemets of c are extracted.
A1 = A(idx1);
then we find minimum of the extracted elements:
mn = min(A1);
again we use logical indexing to find elements of A that are equal to its minimum.
idx2 = A == mn;
finally using find the logical index idx2 converted to linear index.
result = find (idx2);
First convert your Matrix to a vector (otherwise the minimum of a Matrix is confusing, it might mean the minimum of each column).
Then you can sort the Vector and get the indexes
[val idx] = sort(A(:));
You can then use the indexes to sort your vector c
c = c(idx);
And finally get the first non-zero element of c:
c = c(c~=0);
result = c(1);

using Matlab, how to find the maximum value over a certain range?

i want to know the coding to find the maximum value, over a certain range.
i already coded like below.
f=f'
ac_yyyy_f=ac_yyyy_f'
[row,col] = ind2sub(size(ac_yyyy_f),find(ac_yyyy_f==max(ac_yyyy_f)))
but the problem is, sometimes the maximum value of Y axis choosen by my code is not what i want.
the X axis has the range of 0 to 100000 and i want the maximum between 20000 to 100000. the problem is sometimes the max value show up at the range of 0 to 20000.
How can i figure this out?
Use the max() function:
%let R be your range of values
R = [2 1 7 4];
[value, index] = max(R);
In the above example, value will be 7 and index will be 3
For more info: http://fr.mathworks.com/help/matlab/ref/max.html
I'm using a vector of random integers to stand in for your function output.
a = floor(rand(1,100000)*100);
[val, idx] = max(a(20000:100000));
You want to use the max function here to find the maximum value rather than find.
Now, the other part of the task is getting the max value from a certain part of your matrix. You can pass just a subset of a vector or matrix to a function by indexing it with a range of values. Note that idx gives you the position of val within a(20000:100000). If you need the position within a, you need to use idx+19999.
Also, you should take a look at the matrix indexing reference—there are many different and fun ways to index a matrix—because indexing is one of the most important features of matlab.
Here's the reference for the max function:
http://www.mathworks.com/help/matlab/ref/max.html
And the reference for indexing:
http://www.mathworks.com/help/matlab/math/matrix-indexing.html
You can use the max function with a subset of your array. It will return the maximum value, as well as the index where it is located. Be sure to correct the index it returns you based on your desired range. Like this:
%//create an array of 100,000 values to play with.
f=floor(rand(100000,1).*100);
%//find the max between f(20000) and f(100000)
[myMax, I] = max( f(20000:100000) );
%//correct the index based on where we started looking
%//for the max. Subtract 1 because it's MATLAB!
myIndex = I+20000-1;
This results in:
>> myMax
myMax =
99
>> myIndex
myIndex =
20045
>> f(myIndex)
ans =
99

How can I find the indices of the 2 smallest elements in a vector without sorting?

I'm trying to find the two smallest elements of a 1xn vector. The catch is that I can't sort it because the indices are linearly dependent upon the values (so sorting the values will screw up to original indices) AND 0 can be one of the elements. Also, elements can repeat. Here's a simplified example of my code:
a = [1,5,8,7,1];
find(a==min(a))
ans =
1 5
For a, this is the answer I was expecting.
b = [0,8,6,1,9];
find(b==min(b))
ans =
1
For b, I need it to find the 0 and the 1 so it should give me back 1 and 4 respectively for the indices. Thanks in advance!
Phil Goddard's answer is perfectly acceptable. However, you did say that you want to do this without sorting, so I'm assuming you don't want to use the sort function at all. What you can do is use min twice. Once you invoke it the first time and you find the index of the minimum element, you would set this location in your array to NaN, then run min an additional time. By setting the location to NaN, you would effectively skip the element that is equal to the smallest at that point in time. After you call min the second time, you'll get the second smallest element.
One small thing you'll need to do afterwards is to clear off the NaN you set in the array after the first min call. You do this by extracting what the minimum value was after the first call, in addition to where this minimum value was located. Once you call min a second time, you'd reset the location of where the first minimum was from NaN back to its original value.
In other words:
a = [1,5,8,7,1];
[min1,ind1] = min(a);
a(ind1) = NaN;
[~,ind2] = min(a);
a(ind1) = min1; %// Copy back to ensure we get original data back
ind1 and ind2 will contain the locations of the two smallest values in a. With your example, I get:
disp([ind1 ind2])
1 5
Similarly, for b, this is what we get with the above code:
disp([ind1 ind2])
1 4
You should use the second output from sort,
>> [~,idx] = sort(a);
>> idx(1:2)
ans =
1 5
>> [~,idx] = sort(b);
>> idx(1:2)
ans =
1 4

N-Dimensional Histogram Counts

I am currently trying to code up a function to assign probabilities to a collection of vectors using a histogram count. This is essentially a counting exercise, but requires some finesse to be able to achieve efficiently. I will illustrate with an example:
Say that I have a matrix X = [x1, x2....xM] with N rows and M columns. Here, X represents a collection of M, N-dimensional vectors. IN other words, each of the columns of X is an N-dimensional vector.
As an example, we can generate such an X for M = 10000 vectors and N = 5 dimensions using:
X = randint(5,10000)
This will produce a 5 x 10000 matrix of 0s and 1s, where each column is represents a 5 dimensional vector of 1s and 0s.
I would like to assign a probability to each of these vectors through a basic histogram count. The steps are simple: first find the unique columns of X; second, count the number of times each unique column occurs. The probability of a particular occurrence is then the #of times this column was in X / total number of columns in X.
Returning to the example above, I can do the first step using the unique function in MATLAB as follows:
UniqueXs = unique(X','rows')'
The code above will return UniqueXs, a matrix with N rows that only contains the unique columns of X. Note that the transposes are due to weird MATLAB input requirements.
However, I am unable to find a good way to count the number of times each of the columns in UniqueX is in X. So I'm wondering if anyone has any suggestions?
Broadly speaking, I can think of two ways of achieving the counting step. The first way would be to use the find function, though I think this may be slow since find is an elementwise operation. The second way would be to call unique recursively as it can also provide the index of one of the unique columns in X. This should allow us to remove that column from X and redo unique on the resulting X and keep counting.
Ideally, I think that unique might already be doing some counting so the most efficient way would probably be to work without the built-in functions.
Here are two solutions, one assumes all values are either 0's or 1's (just like the example in your description), the other does not. Both codes should be very fast (more so the one with binary values), even on large data.
1) only zeros and ones
%# random vectors of 0's and 1's
x = randi([0 1], [5 10000]); %# RANDINT is deprecated, use RANDI instead
%# convert each column to a binary string
str = num2str(x', repmat('%d',[1 size(x,1)])); %'
%# convert binary representation to decimal number
num = (str-'0') * (2.^(size(s,2)-1:-1:0))'; %'# num = bin2dec(str);
%# count frequency of how many each number occurs
count = accumarray(num+1,1); %# num+1 since it starts at zero
%# assign probability based on count
prob = count(num+1)./sum(count);
2) any positive integer
%# random vectors with values 0:MAX_NUM
x = randi([0 999], [5 10000]);
%# format vectors as strings (zero-filled to a constant length)
nDigits = ceil(log10( max(x(:)) ));
frmt = repmat(['%0' num2str(nDigits) 'd'], [1 size(x,1)]);
str = cellstr(num2str(x',frmt)); %'
%# find unique strings, and convert them to group indices
[G,GN] = grp2idx(str);
%# count frequency of occurrence
count = accumarray(G,1);
%# assign probability based on count
prob = count(G)./sum(count);
Now we can see for example how many times each "unique vector" occurred:
>> table = sortrows([GN num2cell(count)])
table =
'000064850843749' [1] # original vector is: [0 64 850 843 749]
'000130170550598' [1] # and so on..
'000181606710020' [1]
'000220492735249' [1]
'000275871573376' [1]
'000525617682120' [1]
'000572482660558' [1]
'000601910301952' [1]
...
Note that in my example with random data, the vector space becomes very sparse (as you increase the maximum possible value), thus I wouldn't be surprised if all counts were equal to 1...

Different results using == and find in MATLAB

I have created a sparse matrix using MEX and also created a sparse matrix using MATLAB. To fill in the values of the matrix i have used same formula.
Now to check if the both the matrices are equal I used result=(A==B). result returns 1 for all indices, which implies that all the matrix elements are equal.
But if I do find(A-B) it returns some indices, which indicates that at these indices the values are non-zero. How is this possible?
Note: When i compare the value at these indices it shows equal !
I'm guessing you have values of infinity cropping up in your matrices at the same points. For example:
>> A = Inf;
>> B = Inf;
>> A == B
ans =
1 %# They are treated as equal...
>> A-B
ans =
NaN %# ...but their difference actually results in NaN...
>> find(A-B)
ans =
1 %# ...which is treated as a non-zero value.
The discrepancy here results from the fact that certain operations involving infinity result in NaN values. You can check to see if you have any infinities in A and B by using the function ISINF like so:
any(isinf(A(:)))
any(isinf(B(:)))
And if you get a value of 1 (i.e. true), then the presence of infinities is likely the source of your discrepancy.