Just wondering if there is a way to construct a tumbling window in python. So for example if I have list/ndarray , listA = [3,2,5,9,4,6,3,8,7,9]
. Then how could I find the maximum of the first 3 items (3,2,5) -> 5, and then the next 3 items (9,4,6) -> 9 and so on… Sort of like breaking it up to sections and finding the max. So the final result would be list [5,9,8,9]
Advertisement
Answer
Approach #1: One-liner for windowed-max using np.maximum.reduceat
–
JavaScript
x
3
1
In [118]: np.maximum.reduceat(listA,np.arange(0,len(listA),3))
2
Out[118]: array([5, 9, 8, 9])
3
Becomes more compact with np.r_
–
JavaScript
1
2
1
np.maximum.reduceat(listA,np.r_[:len(listA):3])
2
Approach #2: Generic ufunc way
Here’s a function for generic ufuncs and that window length as a parameter –
JavaScript
1
9
1
def windowed_ufunc(a, ufunc, W):
2
a = np.asarray(a)
3
n = len(a)
4
L = W*(n//W)
5
out = ufunc(a[:L].reshape(-1,W),axis=1)
6
if n>L:
7
out = np.hstack((out, ufunc(a[L:])))
8
return out
9
Sample run –
JavaScript
1
5
1
In [81]: a = [3,2,5,9,4,6,3,8,7,9]
2
3
In [82]: windowed_ufunc(a, ufunc=np.max, W=3)
4
Out[82]: array([5, 9, 8, 9])
5
On other ufuncs –
JavaScript
1
9
1
In [83]: windowed_ufunc(a, ufunc=np.min, W=3)
2
Out[83]: array([2, 4, 3, 9])
3
4
In [84]: windowed_ufunc(a, ufunc=np.sum, W=3)
5
Out[84]: array([10, 19, 18, 9])
6
7
In [85]: windowed_ufunc(a, ufunc=np.mean, W=3)
8
Out[85]: array([3.33333333, 6.33333333, 6. , 9. ])
9
Benchmarking
Timings on NumPy solutions on array data with sample data scaled up by 10000x
–
JavaScript
1
16
16
1
In [159]: a = [3,2,5,9,4,6,3,8,7,9]
2
3
In [160]: a = np.tile(a, 10000)
4
5
# @yatu's soln
6
In [162]: %timeit moving_maxima(a, w=3)
7
435 µs ± 8.54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
8
9
# From this post - app#1
10
In [167]: %timeit np.maximum.reduceat(a,np.arange(0,len(a),3))
11
353 µs ± 2.55 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
12
13
# From this post - app#2
14
In [165]: %timeit windowed_ufunc(a, ufunc=np.max, W=3)
15
379 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
16