How to index a matrix with the column maxima of other matrix - matlab

I have 2 matrices A and B.
I find the max values in the columns of A, and keep their indices in I. So far so good.
Now, I need to choose those arrays of B with the same index as stored in I. I don't know how to do this.
See below:
A = [1,2,3; 0,8,9]
B = [0,1,2; 4,2,3]
[~,I] = max(A)
h = B(I)
I need to get these values of B:
h = [0 2 3]
But the code results in a different one. How can I fix it?
A =
1 2 3
0 8 9
B =
0 1 2
4 2 3
I =
1 2 2
h =
0 4 4
Thanks in advance

The max function how you used it works like
If A is a matrix, then max(A) is a row vector containing the maximum value of each column.
so M = max(A) is equivalent to M = max(A,[],1). But rather use the third input if you're not sure.
If you use max to find the maxima in the columns of the matrix, it returns the row indices. The column indices are for your case simply 1:size(A,2) = [1 2 3].
Now you need to convert your row and column indices to linear indices with sub2ind:
%// data
A = [1,2,3; 0,8,9]
B = [0,1,2; 4,2,3]
%// find maxima of each column in A
[~, I] = max( A, [], 1 ) %// returns row indices
%// get linear indices for both, row indices and column indices
I = sub2ind( size(A), I, 1:size(A,2) )
%// index B
h = B(I)
returns:
h =
0 2 3

Related

How to update image values by identifying unique locations in MATLAB?

I have a image matrix named final_img. I have image location matrix with rows and columns is given below
a =
1 1
1 2
2 1
2 2
3 1
3 2
1 1
2 2
and values of this locations are
b =
1
2
3
4
5
6
7
8
In above given locations, some are repeating eg: location [1 1] . I can identify unique locations by using following code
[uniquerow, ~, rowidx] = unique(a, 'rows');
noccurrences = accumarray(rowidx, 1);
I need to update unique image locations by summing image location values. Eg: location [1 1] is repeating twice and corresponding value in b are 1 and 7. So
final_img(1,1) should be 1+7=8;
How can I implement this algorithm in MATLAB without using for loop?
You can use the sparse function, which automatically adds all values corresponding to the same coordinates:
final_img = full(sparse(a(:,1), a(:,2), b));
This will create a matrix as small as possible according to the input.
If you want an ouput that is as small as possible with the resctriction that it be square:
M = max(a(:));
final_img = full(sparse(a(:,1), a(:,2), b, M, M));
If you want to specify size of the output:
M = 3;
N = 3;
final_img = full(sparse(a(:,1), a(:,2), b, M, N));
You were so incredibly close:
[final_coords, ~, rowidx] = unique(a, 'rows');
final_vals = accumarray(rowidx, b);
Then to get it to image form:
% empty matrix with size of your image
final_img = zeros(max(final_coords,[],1));
% get linear indexes from coordinates
ind = sub2ind(size(final_img), final_coords(:,1), final_coords(:,2));
% fill image
final_img(ind) = final_vals;

Matlab: How to read data into a matrix

I have a data file matrix.txt, it has three columns. The first column stores the row index, the second column stores the column index, the third column stores the value. How do I read these into a matrix called mat. To be explicit, suppose our mat is a n*n square matrix, let n=2 for instance. In the text file, it has:
0 0 10
1 1 -10
The element in mat not specified is 0. Thus mat is supposed to be:
mat = 10 0
0 -10
How do I achieve this?
This should work for the generic 2-D case.
% Read in matrix specification
fID = fopen('matrix.txt');
tmp = fscanf(fID, '%u%u%f', [3 inf])';
fclose(fID);
% Use the maximum row and column subscripts to obtain the matrix size
tmp(:, 1:2) = tmp(:, 1:2) + 1; % MATLAB doesn't use 0-based indexing
matsize = [max(tmp(:,1)), max(tmp(:,2))];
% Convert subscripts to linear indices
lidx = sub2ind(matsize, tmp(:,1), tmp(:,2));
mat = zeros(matsize); % Initialize matrix
mat(lidx) = tmp(:,3); % Assign data
Using a sample matrix.txt:
0 0 10
1 1 -10
1 2 20
We receive:
>> mat
mat =
10 0 0
0 -10 20
Since in MATLAB, indices begin with 1 (not zero), we should add 1 to our indices in code.
r and c stand for row and column.
Alsom and n is for m by n zero matrix
A = importdata('matrix.txt');
r = A(:, 1)';
c = A(:, 2)';
m = max(r);
n = max(c);
B = zeros(m + 1, n + 1);
for k = 1:size(A,1);
B(r(k) + 1, c(k) + 1) = A(k, 3);
end
Result:
B =
10 0
0 -10
I see I am too slow, but I decided post my answer anyway...
I initialized matrix A as a vector, and used reshape:
%Load all file to matrix at once
%You may consider using fopen and fscanf, in case Matrix.txt is not ordered perfectly.
row_column_val = load('Matrix.txt', '-ascii');
R = row_column_val(:, 1) + 1; %Get vector of row indexes (add 1 - convert to Matalb indeces).
C = row_column_val(:, 2) + 1; %Get vector of column indexes (add 1 - convert to Matalb indeces).
V = row_column_val(:, 3); %Get vector of values.
nrows = max(R); %Number of rows in matrix.
ncols = max(C); %Number of columns in matrix.
A = zeros(nrows*ncols, 1); %Initialize A as a vector instead of a matrix (length of A is nrows*ncols).
%Put value v in place c*ncols + r for all elements of V, C and R.
%The formula is used for column major matrix (Matlab stored matrices in column major format).
A((C-1)*nrows + R) = V;
A = reshape(A, [nrows, ncols]);

Matlab - determine column wise the ordinal rank of values in a matrix

I have following mxn matrix:
X = [-0.0061 -0.0108 -0.0098;
0.0092 0.0237 0.0114;
-0.0026 -0.0082 0.0035;
-0.0033 0.0257 -0.0106]
What i want to do is to assign the ordinal rank within each column, i.e. to get following matrix Y.
Y = [1 1 2;
4 3 4;
3 2 3;
2 4 1]
I tried it with [~,~,ranking] = unique(X) but unfortunately there it considers all matrix elements and ranks them ordinally and does not do the job column wise. Furthermore it puts the ranks in a column vector and not in the shape of upper Y matrix.
Thanks for any help!
Just use the second output of sort. Thanks to #beaker for the correction (see comments below);
[~, result] = sort(X, 1);
[~, result] = sort(result, 1);

How to get the indices of max values in a matrix,and map them to the indices of another same sized matrix?

I have two 16x12 matrices, In matrix A, I should sort in descending order and find the first 10 max values. But I should know the max values' indices before being sorted.
Finally, I should give those indices to the second matrix and find the values in that matrix.
I tried with for-loop but it doesn't give me accurate answer.
This should work:
[~,I] = sort(A(:), 'descend');
vals = B(I(1:10));
For example:
>> A = [ 4 2; 1 5];
>> B = [ 7 8; 0 NaN];
>> [~,I] = sort( A(:), 'descend' );
>> vals = B(I(1:2))
vals =
NaN
7

Vector as column index in matrix

Given a matrix A (mxn) and a vector B (mx1) I want to create a vector C (mx1) in which each row element is the row element of A from a column indexed by B.
Is it possible to do this, without using loops?
A = [1 2; 3 4; 5 6];
B = [2 1 1].';
Then I want:
C = [2 3 5].';
Convert the column subscripts of B to linear indices and then use them to reference elements in A:
idx = sub2ind(size(A), (1:size(A, 1)).', B);
C = A(idx);
(for more information, read the part about linear indexing in this answer).