Create rolling-window matrix from vector
    9 Ansichten (letzte 30 Tage)
  
       Ältere Kommentare anzeigen
    
    Hamad
      
 am 22 Jan. 2015
  
    
    
    
    
    Bearbeitet: Anu Nair
 am 14 Jul. 2018
            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 Kommentar
Akzeptierte Antwort
  David Young
      
 am 2 Feb. 2015
        
      Bearbeitet: David Young
      
 am 2 Feb. 2015
  
      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)
Weitere Antworten (3)
  Stephen23
      
      
 am 22 Jan. 2015
        
      Bearbeitet: Stephen23
      
      
 am 2 Feb. 2015
  
      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 Kommentare
  David Young
      
 am 2 Feb. 2015
				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
      
 am 24 Okt. 2017
        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 Kommentare
  Anu Nair
 am 14 Jul. 2018
        
      Bearbeitet: Anu Nair
 am 14 Jul. 2018
  
      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 Kommentare
Siehe auch
Kategorien
				Mehr zu Creating and Concatenating Matrices finden Sie in Help Center und File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




