Efficient way to split a vector into Matrix

1 vue (au cours des 30 derniers jours)
RoJo
RoJo le 14 Avr 2011
Hi,
I am looking for an efficient way to do the following:
Take an input vector, e.g B = [2;5;8;11;3;6;9;15]
and return the array
D = [2 5 8 11 3;5 8 11 3 6;8 11 3 6 9]
, ie each column is a rolling subvector of B
My attempt below works but it causes a bottleneck in my programme. I have been trying to vectorize it but am finding it difficult.
If somebody has thoughts I would appreciate a pointer.
Thanks!
function ret = MakeMatrix(inputVector, inputLookbackPeriod, numPeriodsToCalculate)
m_Array = zeros(inputLookbackPeriod, numPeriodsToCalculate);
for i=1:numPeriodsToCalculate
m_Array(:,i) = inputVector(i:i+inputLookbackPeriod-1,1);
end
end

Réponse acceptée

the cyclist
the cyclist le 14 Avr 2011
Here is an obscure way, using a Hilbert matrix. It is semi-coincidental that the indexing you need is exactly the (element-by-element inverse of the) Hilbert matrix.
For something less esoteric, you could probably use the filter command.
function m_Array = MakeMatrixFast(inputVector, inputLookbackPeriod, numPeriodsToCalculate)
H = 1./hilb(max(inputLookbackPeriod,numPeriodsToCalculate));
H = H(1:inputLookbackPeriod,1:numPeriodsToCalculate);
m_Array = inputVector(H);
end
  2 commentaires
RoJo
RoJo le 14 Avr 2011
Thanks. This does what I was asking. One point is that as I increase the argument to hilb, e.g 1./hilb(30) the resulting matrix contains 49.000.. which fails inputVector(H). So just needs a conversion before that line.
the cyclist
the cyclist le 14 Avr 2011
Yeah, I should have anticipated that. Can you just put in a rounding command?

Connectez-vous pour commenter.

Plus de réponses (2)

Andrei Bobrov
Andrei Bobrov le 14 Avr 2011
variant
D0 = buffer(B,5,4);
D = D0(2:end-1,4:end)
  2 commentaires
RoJo
RoJo le 14 Avr 2011
Thanks for the reply. I don't have the Signal Processing Toolbox to use the buffer function however.
Teja Muppirala
Teja Muppirala le 14 Avr 2011
You learn something new every day...

Connectez-vous pour commenter.


Matt Fig
Matt Fig le 14 Avr 2011
IDX = ones(3,5,'single');
IDX(:,1) = 1:3;
D = B(cumsum(IDX,2))
Or, to match your functional form:
function m_Array = MakeMatrixFast2(inputVector, inputLookbackPeriod, numPeriodsToCalculate)
IDX = ones(inputLookbackPeriod,numPeriodsToCalculate,'single');
IDX(:,1) = 1:inputLookbackPeriod;
m_Array = inputVector(cumsum(IDX,2));
  2 commentaires
RoJo
RoJo le 14 Avr 2011
Sorry, I didn't refresh the page and see this answer. It works well and is efficient for large/small vectors and lookbacks. Thanks.
Matt Fig
Matt Fig le 14 Avr 2011
That's o.k.! I tested all three algorithms and yours is actually faster than the cyclist's. Mine is somewhat faster than yours for certain inputs.

Connectez-vous pour commenter.

Community Treasure Hunt

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

Start Hunting!

Translated by