Replace specific columns in a matrix with a constant column vector

Solution 1:

From the context of your question, you wish to find a matrix where each column is an identity vector. For an identity vector, each column in this matrix is a non-zero vector where 1 is set in the position of the vector denoted by each position of y and 0 otherwise. Therefore, let's say we had the following example:

y = [1 5 4 3]

You would have y_out as the final matrix, which is:

y_out =

     1     0     0     0
     0     0     0     0
     0     0     0     1
     0     0     1     0
     0     1     0     0

There are several ways to do this. The easiest one would be to declare the identity matrix with eye, then let y pick out those columns that you want from this matrix and place them as columns into your final matrix. If y had all unique values, then we would simply be rearranging the columns of this identity matrix based on y. As such:

y_out = eye(max(y));
y_out = y_out(:,y)

y_out =

     1     0     0     0
     0     0     0     0
     0     0     0     1
     0     0     1     0
     0     1     0     0

Another way would be to declare a sparse matrix, where each row index is simply those elements from y and each column index is increasing from 1 up to as many elements as we have y:

y_out = sparse(y, 1:numel(y), 1, max(y), numel(y));
y_out = full(y_out)

y_out =

     1     0     0     0
     0     0     0     0
     0     0     0     1
     0     0     1     0
     0     1     0     0

One more way would be to use sub2ind to find linear indices into your matrix, then access those elements and set them to 1. Therefore:

ind = sub2ind([max(y) numel(y)], y, 1:numel(y));
y_out = zeros(max(y), numel(y));
y_out(ind) = 1

y_out =

     1     0     0     0
     0     0     0     0
     0     0     0     1
     0     0     1     0
     0     1     0     0

Solution 2:

This works even if y has "missing" values:

n = numel(y);
y_matrix = zeros(n, max(y));
y_matrix((1:n) + (y-1)*n) = 1;

Example:

y = [1 5 3 2];

gives

y_matrix =
     1     0     0     0     0
     0     0     0     0     1
     0     0     1     0     0
     0     1     0     0     0

Solution 3:

You can use bsxfun:

y_out =  bsxfun(@eq, (1:max(y)).', y);