split a vecor into several parts (of different sizes) to later fill a matrix.

Hi!
I have a vector V and I want to split it in several parts of different known sizes (in the example below, the sizes would be: [3,6,5,...]), to build a matrix like this one (example):
M = [ V(1) V(4) V(10) ....
V(2) V(5) V(11) ....
V(3) V(6) V(12)
0 V(7) V(13)
0 V(8) V(14)
0 V(9) 0
0 0 0 ]
so each column is padded with zeros until a certain number of rows is reached (fixed a priori)
Any idea of how to do that WITHOUT using a loop (for ... end)? i.e. doing it in just one step (like matricial operation) because this has to be done a lot of times and with a loop the required time would be too much.
Thanks in advance!
Merce

3 commentaires

I can't understand how your matrix should be structured. Can you please clarify?
My guess is the loop is the fastest way to do this.
I agree with Sean, you already know the size M has to be so you can preallocate M as a matrix of zeros and then fill it in a column at a time in a loop

Connectez-vous pour commenter.

Réponses (4)

Andrei Bobrov
Andrei Bobrov le 30 Août 2012
Modifié(e) : Andrei Bobrov le 30 Août 2012
try this is code
V = 10:10:140; % eg
s =[3 6 5];
b = cumsum(s) - s + 1;
i0 = bsxfun(@plus,b,(0:max(diff(b))-1)');
t = bsxfun(@lt,i0,[b(2:end) numel(V)+1]);
i0(~t) = 1;
out = V(i0).*t;
OR
V = 10:10:140;
s =[3 6 5];
a = cellfun(...
@(x,y)[x(:);zeros(max(s)-y,1)],mat2cell(V(:)',1,s),num2cell(s(:)'),'un',0);
out = [a{:}];

2 commentaires

Nice code, but you have an extra row at the bottom filled with zeros. Just a very small change needed:
here
V=(1:15)/pi; % e.g. |
b = [1 4 10 12]; V
i0 = bsxfun(@plus,b,(0:max(diff(b))-1)');
t = bsxfun(@lt,i0,[b(2:end) numel(V)+1]);
i0(~t) = 1;
out = V(i0).*t;
Hello David, thank you for reply, I corrected.

Connectez-vous pour commenter.

Jos (10584)
Jos (10584) le 30 Août 2012
Modifié(e) : Andrei Bobrov le 30 Août 2012
Take a look at MAT2CELL and PADCAT
% data
V = 1:15 ;
sz = [3 5 6 1] ; % lengths
% engine
C = mat2cell(V(:),sz,1) ;
[M,tf] = padcat(C{:}) ;
M(~tf) = 0 ; % replace NaNs by 0, per request
Sean de Wolski
Sean de Wolski le 30 Août 2012
Modifié(e) : Sean de Wolski le 30 Août 2012
I have a simple for-loop showing a 2.7x and a 9.5x speed up over Andrei's solutions for V,S being this size. In general, a for-loop will smoke conversions so cell arrays any time and with the JIT accelerator it can generally hold up to complicated vectorized methods. Consider Andrei's dataset:
function looptest
%Data: same data all
V = 10:10:140; % eg
s =[3 6 5];
times = zeros(1,3);
for ii = 1:100;
%Andrei's first method
tic
b = cumsum(s) - s + 1;
i0 = bsxfun(@plus,b,(0:max(diff(b))-1)');
t = bsxfun(@lt,i0,[b(2:end) numel(V)+1]);
i0(~t) = 1;
out = V(i0).*t;
times(1) = times(1)+toc;
%Andrei's second method
tic;
a = cellfun(...
@(x,y)[x(:);zeros(max(s)-y,1)],mat2cell(V(:)',1,s),num2cell(s(:)'),'un',0);
out2 = [a{:}];
times(2) = times(2)+toc;
%trivial for-loop
tic
ns = numel(s);
out3 = zeros(max(s),ns);
sel = cumsum([1 s(1:end-1)]); %start element
eel = sel+s-1; %end element
for jj = 1:ns
out3(1:s(jj),jj) = V(sel(jj):eel(jj));
end
times(3) = times(3)+toc;
end
disp(times./times(3));
My System: 2.7907 9.5219 1.0000
Note if we blow V and S up a fair amount, Andrei's bsxfun solution does surpass the for-loop for at least a little while.
Thank you for all the comments!
I actually compared the for loop option with mat2cell+padcat and the loop is faster as some of you mentioned. But thanks anyway!

Catégories

En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by