Lets say I have a Python Numpy array a
.
a = numpy.array([1,2,3,4,5,6,7,8,9,10,11])
I want to create a matrix of sub sequences from this array of length 5 with stride 3. The results matrix hence will look as follows:
numpy.array([[1,2,3,4,5],[4,5,6,7,8],[7,8,9,10,11]])
One possible way of implementing this would be using a for-loop.
result_matrix = np.zeros((3, 5)) for i in range(0, len(a), 3): result_matrix[i] = a[i:i+5]
Is there a cleaner way to implement this in Numpy?
The strides of an array tell us how many bytes we have to skip in memory to move to the next position along a certain axis. For example, we have to skip 4 bytes (1 value) to move to the next column, but 20 bytes (5 values) to get to the same position in the next row.
NumPy Arrays are faster than Python Lists because of the following reasons: An array is a collection of homogeneous data-types that are stored in contiguous memory locations. On the other hand, a list in Python is a collection of heterogeneous data types stored in non-contiguous memory locations.
numpy. array is just a convenience function to create an ndarray ; it is not a class itself. You can also create an array using numpy. ndarray , but it is not the recommended way.
Numpy is a library in Python adding support for large multidimensional arrays and matrices along with high level mathematical functions to operate these arrays.
Approach #1 : Using broadcasting
-
def broadcasting_app(a, L, S ): # Window len = L, Stride len/stepsize = S nrows = ((a.size-L)//S)+1 return a[S*np.arange(nrows)[:,None] + np.arange(L)]
Approach #2 : Using more efficient NumPy strides
-
def strided_app(a, L, S ): # Window len = L, Stride len/stepsize = S nrows = ((a.size-L)//S)+1 n = a.strides[0] return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S*n,n))
Sample run -
In [143]: a Out[143]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) In [144]: broadcasting_app(a, L = 5, S = 3) Out[144]: array([[ 1, 2, 3, 4, 5], [ 4, 5, 6, 7, 8], [ 7, 8, 9, 10, 11]]) In [145]: strided_app(a, L = 5, S = 3) Out[145]: array([[ 1, 2, 3, 4, 5], [ 4, 5, 6, 7, 8], [ 7, 8, 9, 10, 11]])
Starting in Numpy 1.20
, we can make use of the new sliding_window_view
to slide/roll over windows of elements.
And coupled with a stepping [::3]
, it simply becomes:
from numpy.lib.stride_tricks import sliding_window_view # values = np.array([1,2,3,4,5,6,7,8,9,10,11]) sliding_window_view(values, window_shape = 5)[::3] # array([[ 1, 2, 3, 4, 5], # [ 4, 5, 6, 7, 8], # [ 7, 8, 9, 10, 11]])
where the intermediate result of the sliding is:
sliding_window_view(values, window_shape = 5) # array([[ 1, 2, 3, 4, 5], # [ 2, 3, 4, 5, 6], # [ 3, 4, 5, 6, 7], # [ 4, 5, 6, 7, 8], # [ 5, 6, 7, 8, 9], # [ 6, 7, 8, 9, 10], # [ 7, 8, 9, 10, 11]])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With