Create rolling-window matrix from vector

15 ビュー (過去 30 日間)
Hamad
Hamad 2015 年 1 月 22 日
編集済み: Anu Nair 2018 年 7 月 14 日
Hi, I have a vector from which I would like to create a rolling-window array with a given window length. For example:
vector = [1 2 3 4 5 6 7];
windowLength = 3;
Then the function
matrix = createRollingWindow(vector,windowLength)
would create something like:
matrix =
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
I have tried this successfully with a for-loop, but I wonder if there is a built-in function in MATLAB or some other vectorized solution which I've missed that can do this efficiently (actual problem is very large).
Thank you very much in advance, Hamad
  1 件のコメント
Stephen23
Stephen23 2015 年 1 月 22 日
編集済み: Stephen23 2015 年 1 月 22 日
+1 for asking the question clearly, complete with example inputs and outputs.

サインインしてコメントする。

採用された回答

David Young
David Young 2015 年 2 月 2 日
編集済み: David Young 2015 年 2 月 2 日
If the function is to accept a vector as input, as in the question:
function output = createRollingWindow(vector, n)
% CREATEROLLINGWINDOW returns successive overlapping windows onto a vector
% OUTPUT = CREATEROLLINGWINDOW(VECTOR, N) takes a numerical vector VECTOR
% and a positive integer scalar N. The result OUTPUT is an MxN matrix,
% where M = length(VECTOR)-N+1. The I'th row of OUTPUT contains
% VECTOR(I:I+N-1).
l = length(vector);
m = l - n + 1;
output = vector(hankel(1:m, m:l));
end
To test:
createRollingWindow(1:7, 3)
Or, if the function is to accept a scalar as input, and generate a sequence, as in Hamad's comment to Stephen's solution, then:
function output = createRollingWindow(l, n)
% CREATEROLLINGWINDOW gives successive overlapping windows onto a sequence
% OUTPUT = CREATEROLLINGWINDOW(NVECTOR, NWINDOW) takes two positive
% integer scalars. The result OUTPUT is an MxNWINDOW matrix, where M =
% NVECTOR-NWINDOW+1. The I'th row of OUTPUT contains I:I+NWINDOW-1.
m = l - n + 1;
output = hankel(1:m, m:l);
end
To test:
createRollingWindow(7, 3)
  1 件のコメント
Hamad
Hamad 2015 年 2 月 4 日
Thank you very much for your contribution. Hamad.

サインインしてコメントする。

その他の回答 (3 件)

Stephen23
Stephen23 2015 年 1 月 22 日
編集済み: Stephen23 2015 年 2 月 2 日
Here is one way without using a loop, for a general solution for any input vector (not just 1:N):
vec = [1,2,3,4,5,6,7];
win = 3;
out2 = arrayfun(@(n)circshift(vec,[0,1-n]), 1:win, 'UniformOutput',false);
out2 = vertcat(out2{:});
out2 = out2(:,1:end-win+1);
Although it might still be faster to keep an explicit for loop:
for a = win:-1:2
out1(a,:) = circshift(vec,[0,1-a]);
end
out(1,:) = vec;
out1 = out1(:,1:end-win+1);
EDIT: A robust hankel based solution is also possible, for any input vector:
>> A = [101,102,103,104,105,106,107];
>> X = hankel(1:5, 5:7).';
>> A(X)
ans =
101 102 103 104 105
102 103 104 105 106
103 104 105 106 107
  2 件のコメント
Hamad
Hamad 2015 年 1 月 22 日
編集済み: Hamad 2015 年 1 月 22 日
Thanks very much Stephen, I have also created the following
function output = createRollingWindow(nPointsInData,nPointsPerWindow)
output = repmat((1:nPointsPerWindow)',1,nPointsInData) + repmat(0:nPointsInData-1,nPointsPerWindow,1);
output = output(:,1:1+(nPointsInData - nPointsPerWindow))';
end
which, in this case, I will call with input arguments 7 and 3. I will profile all the answers I receive and then accept the most efficient. Thank you very much for your contribution.
Hamad
David Young
David Young 2015 年 2 月 2 日
Hamad, I think it's better if the function accepts a vector, as in your question, rather than simply the number of points in the sequence, as in your function in the comment above. If it takes a vector it can be much more general.
If in fact you always just want the result for a sequence of the form 1:N, you can use the hankel function - for your original example it would be
hankel(1:5, 5:7)

サインインしてコメントする。


Reza Bonyadi
Reza Bonyadi 2017 年 10 月 24 日
n=3;m=5;repmat(1:n,m,1)+repmat((0:m-1)',1,n) gives what you want.
A more complete version is: n=5;m=100;o=3;repmat(1:n,ceil(m/o),1)+repmat((0:o:m-1)',1,n)
where o controls the overlap (that can be 1, meaning one shift in the next row, 2 meaning 2 shifts, ...., maximum 4 in this example). o can be larger than n but then it wont be a rolling window anymore.

Anu Nair
Anu Nair 2018 年 7 月 14 日
編集済み: Anu Nair 2018 年 7 月 14 日
I also had a similar problem to solve where I required shifted frames with a given frame length and a given hop-length between the starting elements of consecutive frames. I solved this with a similar procedure as described above using repmat(). Following is the example:
a = rand(15);
totalElements = length(a);
windowLength = 5;
shiftLength = 2;
indexMatrix = repmat(1:windowLength, floor((totalElements -
windowLength)/shiftLength) + 1, 1) + repmat((shiftLength*
(0:floor((totalElements - windowLength)/shiftLength)))', 1, windowLength);
shiftedFrames = a(indexMatrix);

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by