Speed up indexing / Repmat operation

I have to following code I'm running:
M=zeros(r,c);
M (:,I)=repmat(Q,1,sum(I));
end
I is a 1-by-c logical vector and Q is r-by-1
So, M starts out as all zeros, and I need certain columns of M (the ones where the value in I is equal to 1) to take on the values in vector Q.
The above code runs fine, but it is surprisingly slow (I'm doing this on a 2400-by-1000 matrix and looping 45 times.) About half of the time is spent doing the repmat() operation and half the time is spent on M (:,I)= part. I've tried replacing the "repmat" with a bsxfun() operation; it gives the same, correct result, but isn't really any faster.
Is there any way I can speed this up?

 Risposta accettata

The bsxfun funciton is always faster than repmat in such situations. I’m not certain that I understand what you want ‘M’ to be.
See if this does what you want:
r = 7; % Create Data
c = 5; % Create Data
I = logical(randi([0 1], 1, c)); % Create Data
Q = randi(9, r, 1); % Create Data
M=zeros(r,c);
M = bsxfun(@times, Q, I);

3 Commenti

This is perfect. Took the calculation time from 0.48 down to 0.2. Thanks!
My pleasure!
You don't really need the M=zeros(r,c) pre-allocation anymore, since the next line sets M directly.

Accedi per commentare.

Più risposte (1)

Thorsten
Thorsten il 25 Lug 2016
Modificato: Thorsten il 25 Lug 2016
nnz(I)
may be faster than sum for logical matrices.
Another way could be to pre-allocate cells of ones for all possible values of sum(I), like
C{1} = 1;
C{2} = ones(1, 2);
C{3} = ones(1, 3);
and so on
and then use
M (:,I) = Q*C{sum(I)};

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by