Cut Peaks And Troughs
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"