1

Let's say I'm given a 1000x1 column vector of with values ranging from 1-10. Now I want to turn this into a 1000x10 matrix, where for each row there is a 1 in the column given by the value in the column vector. I have a correct implementation below, but is there an elegant way to do this without a for loop?

ymat = zeros(1000, 10); y = randi([1,10],1000,1); for i=1:1000 ind = y(i); ymat(i,ind)=1; end 
1
  • The above duplicate answers your problem. Simply transpose the result to get what you need, or reverse the row and column indices in the answers without transposing. Commented Sep 12, 2016 at 6:34

4 Answers 4

4

We can access any subset of the entries in ymat all at once using the "linear index" of those entries. Since we already have y that contains the column coordinates, and the row coordinates are simply 1:100, We can easily obtain their linear index value with sub2ind, and then set all the indexed values to 1 in ymat:

ymat(sub2ind([1000 10], (1:1000)', y)) = 1 

However note that ymat with the proper size must be created before hand.

Sign up to request clarification or add additional context in comments.

Comments

2

You have set of column indices and corresponding row index should be 1:1000.

There are two options to generate matrix from this.

  1. accumarray

  2. sparse

acccumarray will generate full matrix and sparse will generate sparse matrix.

In your case, the resulting matrix has density of 10% which can be considered as sparse matrix.

% Full matrix using accumarray ymat = accumarray([(1:1000).', y], ones(1000,1), [1000, 10]); % Sparse matrix using sparse ymat = sparse(1:1000, y, ones(1000,1), 1000, 10, 1000); 

Computation time

I run the code with y = 1000 x 1 and y = 10000 x 1.

  1. y = 1000 x 1

size of <code>y</code> is <code>1000 x 1</code>

  1. y = 10000 x 1

size of <code>y</code> is <code>10000 x 1</code>

I added the code suggested by @transversality condition.

It turns out that accumarray is the fastest and sparse is the slowest.

accumarray shows better performance for small size, but the gap between accumarray and bsxfun(@eq) gets smaller as we increase the size of array.

1 Comment

A possible optimization with sparse is that you don't need the ones vector to declare all of the non-zero entries as 1. A special case with sparse is if every non-zero value in the matrix is equal to the same value, you only have to specify a single constant to reflect all of these values. Therefore, just do ymat = sparse(1:1000, y, 1, ...);
1

Sure. Use repmat and bsxfun. E.g.,

bsxfun(@eq,repmat(1:10,numel(y),1),repmat(y,1,10)) 

Answer:

 ... 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 >> 

Comments

0

You can also use the ind2vec function:

ymat=full(ind2vec(y.').') 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.