Create rolling-window matrix from vector
17 次查看(过去 30 天)
显示 更早的评论
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 个评论
采纳的回答
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)
更多回答(3 个)
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 个评论
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
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.
0 个评论
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);
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Loops and Conditional Statements 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!