I want to convert a onehot array to an array of integer values in MATLAB. Given:
Y = 1 0 0
0 1 0
0 1 0
I want to return:
new_y = 1
2
2
You could use find and return only the column indices like so
Y = [1 0 0; 0 1 0; 0 1 0];
[~, new_y] = find(Y); % output: [1; 2; 2] is the col indices of your 1s
Similarly you can return the row indices if your input was the transpose
[new_y, ~] = find(Y); % output: [1; 2; 3] is the row indices of your 1s
The Neural Network toolbox of MATLAB has built-in functions for converting between one-hot vectors and indices: ind2vec() to create a one-hot matrix, and vec2ind() to convert the one-hot matrix back to a vector of indices.
Note: ind2vec returns a sparse matrix. To convert it to a full matrix, you have to use the full() function.
>> Y = full(ind2vec([1, 2, 3]))
Y =
1 0 0
0 1 0
0 0 1
>> new_y = vec2ind(Y)
new_y =
1 2 3
Related
I want to create a special diagonal matrix in MATLAB that
uses [1 1] or any other array as main diagonal elements.
Something like the following:
[1 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1]
How can I do that without using any loop structures?
Let
v = [1 1];
n = 3;
Using kron:
result = kron(eye(n), v);
Using blkdiag:
vv = repmat({v}, 1, n);
result = blkdiag(vv{:});
I would like to apply the function unique to each row of a given matrix, without involving any for loop. Suppose I have the following 4-by-5 matrix
full(A) = [0 1 0 0 1
2 1 0 3 0
1 2 0 0 2
0 3 1 0 0]
where A is the corresponding sparse matrix. As an example using a for loop, I can do
uniq = cell(4,1);
for i = 1:4
uniq{i} = unique(A(i,:));
end
and I would obtain the cell structure uniq given by
uniq{1} = {1}
uniq{2} = {[1 2 3]}
uniq{3} = {[1 2]}
uniq{4} = {[1 3]}
Is there a quicker way to vectorize this and avoid for loops?
I need to apply this to matrices M-by-5 with M large.
Note that I'm not interested in the number of unique elements per row (I know there are around answers for such a problem).
You can use accumarray with a custom function:
A = sparse([0 1 0 0 1; 2 1 0 3 0; 1 2 0 0 2; 0 3 1 0 0]); % data
[ii, ~, vv] = find(A);
uniq = accumarray(ii(:), vv(:), [], #(x){unique(x.')});
This gives:
>> celldisp(uniq)
uniq{1} =
1
uniq{2} =
1 2 3
uniq{3} =
1 2
uniq{4} =
1 3
you can use num2cell(A,2) to convert each row into cell and then cellfun with unique to get cell array of unique values from each row:
% generate large nX5 matrix
n = 5000;
A = randi(5,n,5);
% convert each row into cell
C = num2cell(A,2);
% take unique values from each cell
U = cellfun(#unique,C,'UniformOutput',0);
I want to replace value of n-th column of a matrix, based on a vector values, in a vectorized way.
Input:
[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
Vector:
[2]
[4]
[1]
[3]
Expected output:
[0 1 0 0]
[0 0 0 1]
[1 0 0 0]
[0 0 1 0]
Matlab code with for-loop:
A = zeros(4,4);
b = [2; 4; 1; 3];
for row=1:4
A(row, b(row)) = 1;
endfor
Matlab code with sub2ind:
A = zeros(4,4);
b = [2; 4; 1; 3];
c = [[1:length(b)]' b];
A(sub2ind(size(A), c(:,1), c(:,2))) = 1;
Is there more vectorized way in Matlab? Thank you.
You can use the raw version of sub2ind to solve it in a vectorized manner -
A( (b(:)-1)*size(A,1) + [1:numel(b)]' ) = 1;
How it works: Since elements of b are the column indices and MATLAB follows column-major indexing, so we need to multiply each such column index with the number of rows in A to get us the number of elements before starting that column, which would be (b(:)-1)*size(A,1). Then, add the corresponding row indices i.e. [1:numel(b)]' to give us the final linear indices, same as the ones produced by sub2ind. Finally, index into A with those linear indices and set them to all 1's as per the question's requirement.
So I have a matrix X of size m,10 that is initialized to all zeros.
then I have a vector of size m,1 that contains digits from 1 to 10
what I want to do (hopefully in a single operation with no loops), is for each row of the matrix X and vector y, I want to put a '1' in the column indexed by the value written in the row of vector y.
Here's what I want with a small example: X = [0 0 0; 0 0 0; 0 0 0]; lets say y= [3; 2; 1];
then I would expect the operation to return X = [0 0 1; 0 1 0; 1 0 0]
Do you have a command that can do that easily ?
X(sub2ind(size(X),y',1:numel(y)))=1
or
X((0:numel(y)-1)*size(X,2) + y')=1
I have a m-dimensional vector of integers ranging from 1 to n. These integers are column indexes for m × n matrix.
I want to create a m × n matrix of 0s and 1s, where in m-th row there's a 1 in the column that is specified by m-th value in my vector.
Example:
% my vector (3-dimensional, values from 1 to 4):
v = [4;
1;
2];
% corresponding 3 × 4 matrix
M = [0 0 0 1;
1 0 0 0;
0 1 0 0];
Is this possible without a for-loop?
Of course, that's why they invented sparse matrices:
>> M = sparse(1:length(v),v,ones(length(v),1))
M =
(2,1) 1
(3,2) 1
(1,4) 1
which you can convert to a full matrix if you want with full:
>> full(M)
ans =
0 0 0 1
1 0 0 0
0 1 0 0
Or without sparse matrix:
>> M = zeros(max(v),length(v));
>> M(v'+[0:size(M,2)-1]*size(M,1)) = 1;
>> M = M'
M =
0 0 0 1
1 0 0 0
0 1 0 0
Transposition is used because in matlab arrays are addressed by columns
In Octave, at least as of 3.6.3, you can do this easily using broadcasting:
M = v==1:4