Forming a 'partial' identity-matrix according to a partially filled vector

  • A+

I'm currently forming a matrix from a vector in MATLAB following the scheme described below:

Given is a vector x containing ones and zeros in an arbitrary order, e.g.

x = [0 1 1 0 1];  

From this, I would like to form a matrix Y that is described as follows:

  • Y has m rows, where m is the number of ones in x (here: 3).
  • Each row of Y is filled with a one at the k-th entry, where k is the position of a one in vector x (here: k = 2,3,5)
  • For the example x from above, this would result in:

    Y = [0 1 0 0 0;      0 0 1 0 0;       0 0 0 0 1] 

    This is identical to an identity matrix, that has its (x=0)th rows eliminated.

I'm currently achieving this via the following code:

x = [0,1,1,0,1]; %example from above m = sum(x==1); Y = zeros(m,numel(x)); p = 1; for n = 1:numel(x)     if x(n) == 1         Y(p,n) = 1;        p = p+1;     end   end 

It works but I'm kind of unhappy with it as it seems rather inefficient and inelegant. Any ideas for a smoother implementation, maybe using some matrix multiplications or so are welcome.


Here are a few one-line alternatives:

  • Using sparse:

    Y = full(sparse(1:nnz(x), find(x), 1)); 
  • Similar but with accumarray:

    Y = accumarray([(1:nnz(x)).' find(x(:))], 1); 
  • Using eye and indexing. This assumes Y is previously undefined:

    Y(:,logical(x)) = eye(nnz(x)); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: