MATLAB Answers

Creating a matrix of ones and zeros with location of ones based on array value

123 views (last 30 days)
I need to acheive the following without a loop (for speed):
I have a vertical array where the value of each row tells me which column in a matrix of zeros should be replaced with a one.
For example, if I input:
y = [2; 3];
Then I want MATLAB to produce output:
Y = [0,1,0; 0, 0, 1];
I can acheive the desired output with the following for loop:
Y = zeros(2,3);
for j = 1:3
Y(:,j) = (y==j);
end
In reality, my matrices are much larger and I want to avoid using for loops for speed. Is there anyway I can do this without a for loop?

  1 Comment

madhan ravi
madhan ravi on 9 Apr 2019
@ Melissa Moore :Are you interested in a faster solution still? If yes another solution can be proposed.

Sign in to comment.

Accepted Answer

Kevin Rawson
Kevin Rawson on 8 Apr 2019
One possible way is:
Y = zeros(length(y), max(y));
Y(sub2ind(size(Y), (1:length(y))', y)) = 1;

  0 Comments

Sign in to comment.

More Answers (2)

A. Sawas
A. Sawas on 8 Apr 2019
Edited: A. Sawas on 8 Apr 2019
The best solution I can think of is to use a for loop but will be faster than the one you showed because it will do one scalar assignment in each iteration compared to a vector assignment.
for j=1:2
Y(j,y(j)) = 1;
end
Timewise this is faster than the method propsed above by Kevin Rawson

  1 Comment

Kevin Rawson
Kevin Rawson on 8 Apr 2019
A. Sawas, your method is faster for small arrays, but not for large arrays. I'm using your 10,000x10,000 example with y assigned to the diagonal (see code above).
Sawas method (run 10000 times):
tic;
for i=1:10000
for j=1:length(y)
Y(j,y(j)) = 1;
end
end;
toc;
%Elapsed time is 1.682664 seconds.
Rawson method (run 10000 times):
tic;
for i=1:10000
Y(ind2sub(1:length(y), y)) = 1;
end
toc;
%Elapsed time is 0.596671 seconds.

Sign in to comment.


Melissa Moore
Melissa Moore on 8 Apr 2019
I ended up doing this and it worked:
I = eye(3);
Y = I(y,:);

  3 Comments

A. Sawas
A. Sawas on 8 Apr 2019
I would still argure that this solution is much slower than using the for loop as I showed.
y = (1:1e4)';
tic;
for i=1:length(y)
Y(i,y(i)) = 1;
end
toc;
%Elapsed time is 0.001051 seconds.
tic;
I = eye(length(y));
Y = I(y,:);
toc;
% Elapsed time is 0.741058 seconds.
Kevin Phung
Kevin Phung on 8 Apr 2019
Is Melissa's solution a valid solution?... IMO, I is a diagonal matrix where there are already existing 1's. And this is not what you want.
A. Sawas's is valid and more efficient.
Kevin Rawson
Kevin Rawson on 8 Apr 2019
Kevin Phung, as long as I = eye(max(y)), then Y = I(y,:) will return a valid solution.
However, as A. Sawas pointed out, this is an extremely slow operation, ~700 times slower than A. Sawas' method, and ~1988 times slower than my method for a 10,000x10,000 array.

Sign in to comment.

Sign in to answer this question.

Tags

Products


Release

R2018a