How to generate label matrix from a label vector? [duplicate] - matlab

This question already has answers here:
Replace specific columns in a matrix with a constant column vector
(4 answers)
Closed 8 years ago.
I've a label vector as follows:
y=[3 1 5 3 4 2];
Is there any efficient way to generate the following label matrix?
[0 0 1 0 0;
1 0 0 0 0;
0 0 0 0 1;
0 0 1 0 0;
0 0 0 1 0;
0 1 0 0 0;]
UPDATED:
This post and this post are both good answers. Using the scripts provided by #Nras, the following is to handle the missing labels:
Y=[3 1 5 3 4 2];
labels=unique(Y);
[~,indexes]=ismember(Y,labels);
rows = 1:length(Y); %// row indx
T = zeros(length(Y),length(unique(indexes))); %// A matrix full of zeros
T(sub2ind(size(T),rows ,indexes)) = 1; %// Ones at the desired row/column combinations

Use sub2ind for this problem. Your y determines the columns to use,
the rows are simply always incremented by 1. By using sub2ind the desired row-column-combinations get transformed to a linear index and can then all be adressed in a vectorized way.
y = [3 1 5 3 4 2]; %// column indx
rows = 1:length(y); %// row indx
M = zeros(length(y), max(y)); %// A matrix full of zeros
M(sub2ind(size(M),rows ,y)) = 1; %// Ones at the desired row/column combinations

Related

How to find minimum of each column in MATLAB and sum op all elements of that column?

I have a 300x178 matrix and I want to find the minimum of each column of that matrix, i.e. resulting in a 1x178 array. Then I want to store the sum of all elements but the minimum in each column in the 300x178 matrix on the location/pixel of the minimum value, leaving all other elements zero. How can I do this using MATLAB?
Example:
1 4 6 3
2 6 7 4
5 1 5 7
becomes:
1 0 0 1
0 0 0 0
0 1 1 0
and eventually:
8 0 0 14
0 0 0 0
0 11 18 0
Your example and title do not correspond to the question text. Your example sums all values in a column and stores them at the location of the minimum, which the title also asks. You can do this by making smart use of sub2ind:
A = [1 4 6 3
2 6 7 4
5 1 5 7];
C = zeros(size(A));
[tmp, idx] = min(A); % find the locations of minima
% one liner to store the sum of columns
C(sub2ind(size(A), idx, 1:size(A,2))) = sum(A,1);
C =
8 0 0 14
0 0 0 0
0 11 18 0
If, on the other hand, you're after what your question text asks about, subsequently subtract A on the minimum locations using the same sub2ind trick:
C(sub2ind(size(A), idx, 1:size(A,2))) = C(sub2ind(size(A), idx, 1:size(A,2))) - A(sub2ind(size(A), idx, 1:size(A,2)))
C =
7 0 0 11
0 0 0 0
0 10 13 0
This way you get the sum of all elements but the minimum.
For an in-depth explanation what sub2ind does, read this fantastic Q/A by Luis Mendo keeping in mind that in A(2,3) the 2 and 3 are called subscripts, which, in case of a 3-by-4 matrix, translates to linear index 8.
I cannot test this on my R2007b, but according to the documentation on min you could use [M, I] = min(A, [], 1, 'linear') to get the linear indices into I directly, without going through sub2ind:
C = zeros(size(A));
[tmp, idx] = min(A, [], 1, 'linear');
C(idx) = sum(A, 1);
% Optional, to sum all but the minimum
C(idx) = C(idx) - A(idx);
Small note from the documentation on the occurrence of multiple same-valued minima in your original matrix:
If the smallest element occurs more than once, then I contains the index to the first occurrence of the value.

How to fill the matrix with 0 in matlab [duplicate]

This question already has answers here:
How can I put margins in an image?
(4 answers)
Closed 7 years ago.
Suppose I have a matrix [1 2;3 4], but I need [0 0 0 0;0 1 2 0;0 3 4 0;0 0 0 0], I now how to do it, but is there a function can solve it within one line?
If you have the image processing toolbox, use padarray:
>> A = [1 2; 3 4];
>> B = padarray(A, [1 1])
B =
0 0 0 0
0 1 2 0
0 3 4 0
0 0 0 0
The first input is the matrix you want to pad, and the second input is how many zeroes along the border in each dimension you want to see. You want a 1 element zero border both horizontally and vertically, and so [1 1] is what is required.
However, I'm confused as to why you want this to be in "one-line". If you want a one element border surrounding the original matrix, what's wrong with having multiple lines?
A = [1 2; 3 4];
B = zeros(size(A) + 2);
B(2:end-1,2:end-1) = A;
This is three lines of code, including the definition of your original matrix, but each line is quite clear. You define a new matrix that has 2 more rows and 2 more columns that the original, because you want a 1 element zero boundary around the original matrix, then just place it in the middle.

finding indices of multiple corresponding rows of a matrix in matlab [duplicate]

This question already has answers here:
How can I find indices of each row of a matrix which has a duplicate in matlab?
(3 answers)
Closed 8 years ago.
I have two matrices and I want to find the indices of rows in Matrix B which have the same row values in Matrix A. Let me give a simple example:
A=[1,2,3; 2,3,4; 3,5,7; 1,2,3; 1,2,3; 5,8,6];
B=[1,2,3; 29,3,4; 3,59,7; 1,29,3; 1,2,3; 5,8,6;1,2,3];
For example, for first row in matrix A, The row1, row5, and row7 in Matrix B are correspondences.
I have written below code but it doesn't return back all indices which have the same row value in matrix A and only one of them (row7) is backed !!
A_sorted = sort(A,2,'descend'); % sorting angles
B_sorted = sort(B,2,'descend'); % sorting angles
[~,indx]=ismember(A_sorted,B_sorted,'rows')
the result is
indx_2 =
7
0
0
7
7
6
It means for the first row in matrix A , only one row ( row 7) in Matrix B is available !! But as you can see for first row in matrix A there is three correspondent rows in matrix B (Row 1, row 5 and row 7)
I think the best strategy is to apply ismember to unique rows
%make matrix unique
[B_unique,B2,B3]=unique(B_sorted,'rows')
[~,indx]=ismember(A_sorted,B_unique,'rows')
%For each row in B_unique, get the corresponding indices in B_sorted
indx2=arrayfun(#(x)find(B3==x),indx,'uni',0)
If you want to compare all pairs of rows between A and B, use
E = squeeze(all(bsxfun(#eq, A, permute(B, [3 2 1])), 2));
or equivalently
E = pdist2(A,B)==0;
In your example, this gives
E =
1 0 0 0 1 0 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
1 0 0 0 1 0 1
1 0 0 0 1 0 1
0 0 0 0 0 1 0
The value E(ia,ib) tells you if the ia-th row of A equals the ib-th row of B.

How to shift zero in the last column of a matrix

I have one matrix like below-
A=[1 1 1 1 1;
0 1 1 1 2;
0 0 1 1 3]
But I want to place all the 0 at the end of the row, so A should be like-
A=[1 1 1 1 1;
1 1 1 2 0;
1 1 3 0 0]
How can I do this? Matlab experts please help me.
There you go. Whole matrix, no loops, works even for non-contiguous zeros:
A = [1 1 1 1 1; 0 1 1 1 2; 0 0 1 1 3];
At = A.'; %// It's easier to work with the transpose
[~, rows] = sort(At~=0,'descend'); %// This is the important part.
%// It sends the zeros to the end of each column
cols = repmat(1:size(At,2),size(At,1),1);
ind = sub2ind(size(At),rows(:),cols(:));
sol = repmat(NaN,size(At,1),size(At,2));
sol(:) = At(ind);
sol = sol.'; %'// undo transpose
As usual, for Matlab versions that do not support the ~ symbol on function return, change ~ by a dummy variable, for example:
[nada, rows] = sort(At~=0,'descend'); %// This is the important part.
A more generic example:
A = [1 3 0 1 1;
0 1 1 1 2;
0 0 1 1 3]
% Sort columns directly
[~,srtcol] = sort(A == 0,2);
% Sorted positions
sz = size(A);
pos = bsxfun(#plus, (srtcol-1)*sz(1), (1:sz(1))'); % or use sub2ind
The result
B = A(pos)
B =
1 3 1 1 0
1 1 1 2 0
1 1 3 0 0
there are many ways to do this. one fast way can be easily like this:
a = [1 2 3 4 0 5 7 0];
idx=(find(a==0));
idx =
5 8
b=a; % save a new copy of the vector
b(idx)=[]; % remove zero elements
b =
1 2 3 4 5 7
c=[b zeros(size(idx))]
c =
1 2 3 4 5 7 0 0
You may modify this code as well.
If your zeros are always together, you could use the circshift command. This shifts values in an array by a specified number of places, and wraps values that run off the edge over to the other side. It looks like you would need to do this separately for each row in A, so in your example above you could try:
A(2,:) = circshift(A(2,:), [1 -1]); % shift the second row one to the left with wrapping
A(3,:) = circshift(A(3,:), [1 -2]); % shift the third row two to the left with wrapping
In general, if your zeros are always at the front of the row in A, you could try something like:
for ii = 1:size(A,1) % iterate over rows in A
numShift = numel(find(A(ii,:) == 0)); % assuming zeros at the front of the row, this is how many times we have to shift the row.
A(ii,:) = circshift(A(ii,:), [1 -numShift]); % shift it
end
Try this (just a fast hack):
for row_k = 1:size(A, 1)
[A_sorted, A_sortmap] = sort(A(row_k, :) == 0, 'ascend');
% update row in A:
A(row_k, :) = A(row_k, A_sortmap);
end
Now optimized for versions of MATLAB not supporting ~ as garbage lhs-identifier.
#LuisMendo's answer is inspiring in its elegance, but I couldn't get it to work (perhaps a matlab version thing). The following (based on his answer) worked for me:
Aaux = fliplr(reshape([1:numel(A)],size(A)));
Aaux(find(A==0))=0;
[Asort iso]=sort(Aaux.',1,'descend');
iso = iso + repmat([0:size(A,1)-1]*size(A,2),size(A,2),1);
A=A.';
A(iso).'
I've also asked this question and got a super elegant answer (non of above answers is same) here:
Optimize deleting matrix leading zeros in MATLAB

Matlab, Integer vector to binary matrix without loop [duplicate]

This question already has answers here:
Creating Indicator Matrix
(6 answers)
Closed 7 years ago.
I have a vector with N elements, all integers 1-M. I want to convert this to a NxM matrix with each row containing only zeros except for the i:th element set to one, i being the integer in the vector.
For example:
[1 1 3] => [1 0 0; 1 0 0; 0 0 1]
I currently do this in a loop, like this:
y_vec = zeros(m, num_labels);
for i = 1:m
y_vec(i, y(i)) = 1;
end
Is there a way to do this without a loop?
Yes, there is:
y = [1 1 3];
m = length(y);
num_labels = max(y);
%# initialize y_vec
y_vec = zeros(m,num_labels);
%# create a linear index from {row,y}
idx = sub2ind(size(y_vec),1:m,y);
%# set the proper elements of y_vec to 1
y_vec(idx) = 1;
If you have access to Statistics Toolbox, the command dummyvar does exactly this.
>> dummyvar([1 1 3])
ans =
1 0 0
1 0 0
0 0 1
(This has been asked in Creating Indicator Matrix and Matlab/Octave 1-of-K representation.)
My favorite answer is woodchips' sparse(1:n,labels,1,n,m);.