How to find maximum of previous x elements using numpy

Viewed 80

Question

Is there a way using numpy to sort maximum of range of previous x numbers?


Example

Array of [1, 3, 4, 2, 6, 7, 8, 8, 2, 3], and the range is 3

The output should be [nan, nan, nan, 4, 4, 6, 7, 8, 8, 8].

The first three elements has no 3 previous numbers, so the result is nan.

The fourth elements (2) has the previous numbers of 1, 3, 4, therefore the max is 4.

Sorry for the misleading.

I will provide a second example.

Original array: [1, 3, 4, 6, 2, 8, 2, 3, 1, 2] Output: [nan, nan, nan, 4, 6, 6, 8, 8, 8, 3]

For the last element of output: 3, the reason in the 7th, 8th and 9th elements in original array are 2, 3, 1, therefore the max is 3.

Thanks!

3 Answers

Here is a pandas solution:

win_size = 3
lst = [1, 3, 4, 2, 6, 7, 8, 8, 2, 3]

result = pd.Series(lst).rolling(win_size).max().shift(1).tolist()

Output:

[nan, nan, nan, 4.0, 4.0, 6.0, 7.0, 8.0, 8.0, 8.0]

Note: Outputs are floats - if that bothers you, feel free to convert.

You can't have nan in an np.array that is of data type int, so you can do the following. Change dtype to .astype(float). Set the first 3 values to the minimum of the array minus 1. Sort the values. Change the new minimum values of the first 3 numbers to np.nan.

Note, sorting with np.nan, puts the nan values at the end, which is why I didn't change the values until after sorting.

a = np.array([1, 3, 4, 2, 6, 7, 8, 8, 2, 3]).astype(float)
a[np.arange(3)] = np.min(a-1)
a=np.sort(a)
a[np.arange(3)] = np.nan
a

array([nan, nan, nan,  2.,  2.,  3.,  6.,  7.,  8.,  8.])

You can use maximum.accumulate to get an iterative max

import numpy as np

a = np.array([1, 3, 4, 2, 6, 7, 8, 8, 2, 3])
a = np.maximum.accumulate(a).astype('float')

Converting to float is necessary to set values to np.nan in a numpy array. This clears the unwanted values.

a[np.arange(3)] = np.nan
a

Out:

array([nan, nan, nan,  4.,  6.,  7.,  8.,  8.,  8.,  8.])

For shifted rolling max with numpy if pandas is not an option

a =  np.array([1, 3, 4, 2, 6, 7, 8, 8, 2, 3])
window = 3
rolling = np.lib.stride_tricks.as_strided(a, shape=(len(a)-window, window), strides=a.strides + a.strides)
np.r_[[np.nan]*window, np.max(rolling, axis=1)]

Out:

array([nan, nan, nan,  4.,  4.,  6.,  7.,  8.,  8.,  8.])
Related