I want to do exactly what this guy did:
Python - count sign changes
However I need to optimize it to run super fast. In brief I want to take a time series an
Another way that might suit certain applications is to extend the evaluation of the expression np.diff(np.sign(a)).
If we compare how this expression reacts to certain cases:
np.diff(np.sign([-10, 10])) returns array([2])np.diff(np.sign([-10, 0, 10])) returns array([1, 1])np.diff(np.sign([10, -10])) returns array([-2])np.diff(np.sign([10, 0, -10])) returns array([-1, -1])So we have to evaluate np.diff(...) for the returned patterns in 1. and 2:
sdiff = np.diff(np.sign(a))
rising_1 = (sdiff == 2)
rising_2 = (sdiff[:-1] == 1) & (sdiff[1:] == 1)
rising_all = rising_1
rising_all[1:] = rising_all[1:] | rising_2
and for the cases 3. and 4.:
falling_1 = (sdiff == -2) #the signs need to be the opposite
falling_2 = (sdiff[:-1] == -1) & (sdiff[1:] == -1)
falling_all = falling_1
falling_all[1:] = falling_all[1:] | falling_2
After this we can easily find the indices with
indices_rising = np.where(rising_all)[0]
indices_falling = np.where(falling_all)[0]
indices_both = np.where(rising_all | falling_all)[0]
This approach should be reasonable fast because it can manage without using a "slow" loop.
This combines the approach of several other answers.