Skip to content Skip to sidebar Skip to footer

Cut Peaks And Troughs

Here is an algorithm I would like to implement using numpy: For a given 1D array, calculate the maximum and the minimum over a sliding window. Create a new array, with the first va

Solution 1:

I don't think you can. You can sometime do this kind of iterative computation with unbuffered ufuncs, but this isn't the case. But let me ellaborate...

OK, first the windowing an min/max calculations can be done much faster:

>>>a = np.array([3, 4, 5, 4, 3, 2, 3, 3])>>>len_a = len(a)>>>win = 3>>>win_a = as_strided(a, shape=(len_a-win+1, win), strides=a.strides*2)>>>win_a
array([[3, 4, 5],
       [4, 5, 4],
       [5, 4, 3],
       [4, 3, 2],
       [3, 2, 3],
       [2, 3, 3]])
>>>min_ = np.min(win_a, axis=-1)>>>max_ = np.max(win_a, axis=-1)

Now, lets create and fill up your output array:

>>>out = np.empty((len_a-win+1,), dtype=a.dtype)>>>out[0] = a[0]

If np.clip where a ufunc, we could then try to do:

>>> np.clip(out[:-1], min_[1:], max_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>>outarray([3, 4, 3, 3, 3, 3])

But this doesn't work, because np.clip is not a ufunc, and there seems to be some buffering involved.

And if you apply np.minimum and np.maximum separately, then it doesn't always work:

>>> np.minimum(out[:-1], max_[1:], out=out[1:])
array([3, 3, 3, 3, 3])
>>> np.maximum(out[1:], min_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>>outarray([3, 4, 3, 3, 3, 3])

although for your particular case reversing the other does work:

>>> np.maximum(out[:-1], min_[1:], out=out[1:])
array([4, 4, 4, 4, 4])
>>> np.minimum(out[1:], max_[1:], out=out[1:])
array([4, 4, 4, 3, 3])
>>>outarray([3, 4, 4, 4, 3, 3])

Solution 2:

You can use numpy.clip to perform the clipping operation in a vectorized way, but computing the min and max over a moving window is going to entail some Python loops and a deque or stack structure like you've already implemented.

See these questions for more examples of the approach:

Post a Comment for "Cut Peaks And Troughs"