matlab how to get min value and its index in a matrix - matlab

I have a matrix let's say like this
A=[1 3 6 2 0 4
6 8 9 5 1 4
7 2 7 8 9 2]
I want to get the minimal value where the row is given (r) and the column is in an interval ([c.. c+x]). Also I want the index (number of column of it).
I can get the min with
MinVal=min(A(r,c:c+x))
Example
MinVal=min(A(2,3:3+2))
will give me
% MinVal= 1
The index of this MinVal is I= 5 since it is in the 5th column (I know already the row and don't need it).
But how to get this index ?
If I do like this, I don't get what I want
[MinVal,I]=min(A(r,c:c+x))

It might not be the shortest code, but an easy to understand possibility:
Create a mask indicating which variables you use in your submatrix:
M=false(size(A));
M(r,c:c+x)=true; %use the same indexing operation
Convert to linear indices:
M=find(M);
And use it to translate I to indices in the full matrix:
M(I)

Related

Vectorizing cell find and summing in Matlab

Would someone please show me how I can go about changing this code from an iterated to a vectorized implementation to speed up performance in Matlab? It takes approximately 8 seconds per i for i=1:20 on my machine currently.
classEachWordCount = zeros(nwords_train, nClasses);
for i=1:nClasses % (20 classes)
for j=1:nwords_train % (53975 words)
classEachWordCount(j,i) = sum(groupedXtrain{i}(groupedXtrain{i}(:,2)==j,3));
end
end
If context is helpful basically groupedXtrain is a cell of 20 matrices which represent different classes, where each class matrix has 3 columns: document#,word#,wordcount, and unequal numbers of rows (tens of thousands). I'm trying to figure out the count total of each word, for each class. So classEachWordCount should be a matrix of size 53975x20 where each row represents a different word and each column a different label. There's got to be a built-in function to assist in something like this, right?
for example groupedXtrain{1} might start off like:
doc#,word#,wordcount
1 1 3
1 2 1
1 4 3
1 5 1
1 8 2
2 2 1
2 5 4
2 6 2
As is mentioned in the comments, you can use accumarray to sum up the values in the third column for each unique value in the second column for each class
results = zeros(nwords_train, numel(groupedXtrain));
for k = 1:numel(groupedXtrain)
results(:,k) = accumarray(groupedXtrain{k}(:,2), groupedXtrain{k}(:,3), ...
[nwords_train 1], #sum);
end

Create vector from elements other than diagonal ones

I would like to create a column vector from the elements of a matrix A of size (3,3) that are not on the diagonal. Thus, I would have 6 elements in that output vector. How can I do this?
Use eye and logical negation, although this is no better than Divakar's original answer, and possibly significantly slower for very large matrices.
>> A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> A(~eye(size(A)))
ans =
5
9
4
2
7
14
3
10
15
13
8
12
Use this to get such a column vector, assuming A is the input matrix -
column_vector = A(eye(size(A))==0)
If you don't care about the order of the elements in the output, you can also use a combination of setdiff and diag -
column_vector = setdiff(A,diag(A))
You can also use linear indexing to access the diagonal elements and null them. This will automatically reshape itself to a single vector:
A(1:size(A,1)+1:end) = [];
Bear in mind that this will mutate the original matrix A. If you don't want this to happen, make a copy of your matrix then perform the above operation on that copy. In other words:
Acopy = A;
Acopy(1:size(A,1)+1:end) = [];
Acopy will contain the final result. You need to create a vector starting from 1 and going to the end in increments of the rows of the matrix A added with 1 due to the fact that linear indices are column-major, so the linear indices used to access a matrix progress down each row first for a particular column. size(A,1) will allow us to offset by each column and we add 1 each time to ensure we get the diagonal coefficient for each column in the matrix.
Assuming that the matrix is square,
v = A(mod(0:numel(A)-1, size(A,1)+1) > 0).';

select neighbors and find Top n in Matlab [duplicate]

This question already has answers here:
Get the indices of the n largest elements in a matrix
(4 answers)
Closed 8 years ago.
If I have a matrix like this:
sample = [1 0.21852382 0.090085552 0.219984954 0.446286385;
0.21852382 1 0.104580323 0.138429617 0.169216538;
0.090085552 0.104580323 1 0.237582739 0.105637177;
0.219984954 0.138429617 0.237582739 1 0.192753169;
0.446286385 0.169216538 0.105637177 0.192753169 1 ]
I want to find the top 3 max values in every rows in Matlab.
what i do in Matlab?
and is it true? i want to find top-N method in select neighbors.
I would recommend rewording your question. You say you want the top ten max values in every row, but the matrix you gave has only five columns :/
I think that what you are looking for is something like this.
sample = [1 0.21852382 0.090085552 0.219984954 0.446286385;
0.21852382 1 0.104580323 0.138429617 0.169216538;
0.090085552 0.104580323 1 0.237582739 0.105637177;
0.219984954 0.138429617 0.237582739 1 0.192753169;
0.446286385 0.169216538 0.105637177 0.192753169 1 ]
B = sort(sample,2,'descend') % will sort the rows of the array in descending order
C = B(:,1:N) % Select the top N values.
Hope this answers your question.
If that isn't what you want, try [Y,I] = max(matrix,[],desired_dimension) where Y and an array of the is the actual max values (e.g. [1 1 1 1 1]) and I is the index of the max values, (e.g [1 2 3 4 5])
EDIT
If desired_output = [1 1 1 1 1]', (a column vector, note transpose), then the command to do that is max(matrix,[],2) to operate along the second dimension. This behavior is defined in help max.

Averaging every n elements of a vector in matlab

I would like to average every 3 values of an vector in Matlab, and then assign the average to the elements that produced it.
Examples:
x=[1:12];
y=%The averaging operation;
After the operation,
y=
[2 2 2 5 5 5 8 8 8 11 11 11]
Therefore the produced vector is the same size, and the jumping average every 3 values replaces the values that were used to produce the average (i.e. 1 2 3 are replaced by the average of the three values, 2 2 2). Is there a way of doing this without a loop?
I hope that makes sense.
Thanks.
I would go this way:
Reshape the vector so that it is a 3×x matrix:
x=[1:12];
xx=reshape(x,3,[]);
% xx is now [1 4 7 10; 2 5 8 11; 3 6 9 12]
after that
yy = sum(xx,1)./size(xx,1)
and now
y = reshape(repmat(yy, size(xx,1),1),1,[])
produces exactly your wanted result.
Your parameter 3, denoting the number of values, is only used at one place and can easily be modified if needed.
You may find the mean of each trio using:
x = 1:12;
m = mean(reshape(x, 3, []));
To duplicate the mean and reshape to match the original vector size, use:
y = m(ones(3,1), :) % duplicates row vector 3 times
y = y(:)'; % vector representation of array using linear indices

matrix get min values of a matrix before max values occurred

I was trying to get the min values of a matrix before the max values of the matrix occurred. I have two matrices: matrix data and matrix a. Matrix a is a subset of matrix data and is composed of the max values of matrix data. I have the following code but obviously doing something wrong.
edit:
Matrix a are the max values of matrix data. I derived it from:
for x=1:size(data,1)
a(x)=max(data(x,:));
end
a=a'
clear x
matrix b code:
for x=1:size(data,1)
b(x)=min(data(x,(x<data==a)));
end
b=b'
clear x
matrix data matrix a matrix b
1 2 3 4 4 1
6 5 4 7 7 4
9 6 12 5 12 6
I need all the min values that occurred before to matrix a occurred in matrix data
Short and simple:
[a,idxmax] = max(data,[],2);
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii))), 1:size(data,1));
which is the same as
b=NaN(1,size(data,1)); % preallocation!
for ii=1:size(data,1)
b(ii) = min(data(ii,1:idxmax(ii)));
end
Ignore maximum itself
If you want minimum of everything really before (and not including the maximum), it's possible that the maximum is the first number, and you try taking minimum of an empty matrix. Solution then is to use cell output, which can be empty:
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii)-1)), 1:size(data,1),'uni',false);
Replace empty cells with NaN
If you want to replace empty cells to Nan and then back to a matrix use this:
b(cellfun(#isempty,b))={NaN};
b=cell2mat(b);
or simply use the earlier version and replace b(ii) with NaN when it is equal to a(ii) same outcome:
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii))), 1:size(data,1));
b(b'==a) = NaN
Example:
data=magic(4)
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
outputs:
a' = 16 11 12 15
b =
16 5 6 4
and
b =[1x0 double] [5] [6] [4]
for the 2nd solution using cell output and ignoring the maximum itself also.
And btw:
for x=1:size(data,1)
a(x)=max(data(x,:));
end
a=a'
clear x
can be replaced with
a=max(data,[],2);
It's not pretty but this is the only way I found so far of doing this kind of thing without a loop.
If loops are ok I would recommend Gunther Struyf answer as the most compact use of matlab's in-built array looping function, arrayfun.
Some of the transposition etc may be superfluous if you're wanting column mins instead of row...
[mx, imx] = max(data');
inds = repmat(1:size(data,2), [size(data,1),1]);
imx2 = repmat(imx', [1, size(data,2)]);
data2 = data;
data2(inds >= imx2) = inf;
min(data2');
NOTE: if data is not needed we can remove the additional data2 variable, and reduce the line count.
So to demonstrate what this does, (and see if I understood the question correctly):
for input
>> data = [1,3,-1; 5,2,1]
I get minima:
>> min(data2')
ans = [1, inf]
I.e. it only found the min values before the max values for each row, and anything else was set to inf.
In words:
For each row get index of maximum
Generate matrix of column indices
Use repmat to generate a matrix, same size as data where each row is index of maximum
Set data to infinity where column index > max_index matrix
find min as usual.