I have a numpy array with positive and negative values in.
a = array([1,1,-1,-2,-3,4,5])
I want to create another array which contains a value at each index where a sign change occurs (For example, if the current element is positive and the previous element is negative and vice versa).
For the array above, I would expect to get the following result
array([0,0,1,0,0,1,0])
Alternatively, a list of the positions in the array where the sign changes occur or list of booleans instead of 0's and 1's is fine.
sign() in Python. numpy. sign(array [, out]) function is used to indicate the sign of a number element-wise. For integer inputs, if array value is greater than 0 it returns 1, if array value is less than 0 it returns -1, and if array value 0 it returns 0.
In NumPy, the @ operator means matrix multiplication.
NumPy doesn't do this, so the challenge is to present the same interface as NumPy without explicitly using lazy evaluation.
Using Numpy array, we can easily find whether specific values are present or not. For this purpose, we use the “in” operator. “in” operator is used to check whether certain element and values are present in a given sequence and hence return Boolean values 'True” and “False“.
Something like
a = array([1,1,-1,-2,-3,4,5])
asign = np.sign(a)
signchange = ((np.roll(asign, 1) - asign) != 0).astype(int)
print signchange
array([0, 0, 1, 0, 0, 1, 0])
Now, numpy.roll does a circular shift, so if the last element has different sign than the first, the first element in the signchange array will be 1. If this is not desired, one can of course do a simple
signchange[0] = 0
Also, np.sign considers 0 to have it's own sign, different from either positive or negative values. E.g. the "signchange" array for [-1,0,1] would be [0,1,1] even though the zero line was "crossed" only once. If this is undesired, one could insert the lines
sz = asign == 0
while sz.any():
asign[sz] = np.roll(asign, 1)[sz]
sz = asign == 0
between lines 2 and 3 in the first example.
(numpy.diff(numpy.sign(a)) != 0)*1
import numpy as np
a = np.array([1,1,-1,-2,-3,4,5])
idx1 = np.where(a[:-1] * a[1:] < 0 )[0] +1
idx1
Out[2]: array([2, 5], dtype=int64)
%timeit np.where(a[:-1] * a[1:] < 0 )[0] + 1
4.31 µs ± 15.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
idx2 = np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
idx2
Out[4]: array([2, 5], dtype=int64)
%timeit np.where(np.sign(a[:-1]) != np.sign(a[1:]))[0] + 1
3.94 µs ± 20.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
idx3 = np.where(np.diff(np.sign(a)) != 0)[0] + 1
idx3
Out[6]: array([2, 5], dtype=int64)
%timeit np.where(np.diff(np.sign(a)) != 0)[0] + 1
9.7 µs ± 36.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
For large arrays method 1 is the best.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With