Skip to content

Instantly share code, notes, and snippets.

@nils-werner
Created June 11, 2016 18:45
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nils-werner/9d321441006b112a4b116a8387c2280c to your computer and use it in GitHub Desktop.
Save nils-werner/9d321441006b112a4b116a8387c2280c to your computer and use it in GitHub Desktop.
def sliding_window(data, size, stepsize=1, padded=False, axis=-1, copy=True):
"""
Calculate a sliding window over a signal
Parameters
----------
data : numpy array
The array to be slided over.
size : int
The sliding window size
stepsize : int
The sliding window stepsize. Defaults to 1.
axis : int
The axis to slide over. Defaults to the last axis.
copy : bool
Return strided array as copy to avoid sideffects when manipulating the
output array.
Returns
-------
data : numpy array
A matrix where row in last dimension consists of one instance
of the sliding window.
Notes
-----
- Be wary of setting `copy` to `False` as undesired sideffects with the
output values may occurr.
Examples
--------
>>> a = numpy.array([1, 2, 3, 4, 5])
>>> sliding_window(a, size=3)
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
>>> sliding_window(a, size=3, stepsize=2)
array([[1, 2, 3],
[3, 4, 5]])
See Also
--------
pieces : Calculate number of pieces available by sliding
"""
if axis >= data.ndim:
raise ValueError(
"Axis value out of range"
)
if stepsize < 1:
raise ValueError(
"Stepsize may not be zero or negative"
)
if size > data.shape[axis]:
raise ValueError(
"Sliding window size may not exceed size of selected axis"
)
shape = list(data.shape)
shape[axis] = numpy.floor(data.shape[axis] / stepsize - size / stepsize + 1).astype(int)
shape.append(size)
strides = list(data.strides)
strides[axis] *= stepsize
strides.append(data.strides[axis])
strided = numpy.lib.stride_tricks.as_strided(
data, shape=shape, strides=strides
)
if copy:
return strided.copy()
else:
return strided
@delaram19
Copy link

Tnx for sharing, it helped me a lot!

@dojeda
Copy link

dojeda commented Nov 21, 2019

Hi!
I wanted to report that there is a problem with 2D input data that one can reproduce as:

>>> x = np.arange(30).reshape(3, -1)
>>> x
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])

>>> sliding_window(x, 3, 2)
array([[[ 0,  1,  2],
        [ 2,  3,  4],
        [ 4,  5,  6],
        [ 6,  7,  8]],

       [[10, 11, 12],
        [12, 13, 14],
        [14, 15, 16],
        [16, 17, 18]],

       [[20, 21, 22],
        [22, 23, 24],
        [24, 25, 26],
        [26, 27, 28]]])

which is particularly weird because the epochs have more rows than the input. The correct output should be, in my opinion:

>>> epoch(x, 3, 2)
array([[[ 0,  1,  2],
        [10, 11, 12],
        [20, 21, 22]],

       [[ 2,  3,  4],
        [12, 13, 14],
        [22, 23, 24]],

       [[ 4,  5,  6],
        [14, 15, 16],
        [24, 25, 26]],

       [[ 6,  7,  8],
        [16, 17, 18],
        [26, 27, 28]]])

Which I generated with: https://gist.github.com/dojeda/2250ad463a925a38d7179ec913167ebc
but I am not 100% sure it works on all other cases as well.

@nils-werner
Copy link
Author

Nowadays I recommend using skimage.util.view_as_windows() instead:

skimage.util.view_as_windows(x, (3, 3), step=2)
# array([[[[ 0,  1,  2],
#          [10, 11, 12],
#          [20, 21, 22]],
# 
#         [[ 2,  3,  4],
#          [12, 13, 14],
#          [22, 23, 24]],
# 
#         [[ 4,  5,  6],
#          [14, 15, 16],
#          [24, 25, 26]],
# 
#         [[ 6,  7,  8],
#          [16, 17, 18],
#          [26, 27, 28]]]])

@dojeda
Copy link

dojeda commented Nov 25, 2019

Nice, I didn't known sklearn had this util function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment