Reputation: 451
Hello I have a numpy array as follows:
list_of_values = [-0.5, -0.8, -0.6, -0.2, 0.2, 0.5, 0.7, 0.9, -0.3, 0.2, 0.6, 0.4, 0, 0.2, 0, -0.3, -0.2, 0, -0.6, 0, 0.3]
array= np.array(list_of_values)
I need an array of the same size, having a 1 when the value goes from negative to positive, and a -1 when the value goes from positive to negative, and a 0 for the rest. If there is a 0 in list_of_values, and it bounces back, it should not be considered as the 0 line has been crossed.
This is the exact output that I am looking for
output = [0, 0, 0, 0, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1]
The real list_of_values is large, with 3000+ numbers, so the solution should use Numpy (some for loop is not valid), and it should be quick.
Thank you
Upvotes: 0
Views: 207
Reputation: 15872
You can use numpy.ediff1d
:
>>> import numpy as np
>>> arr = np.array([-1, -0.8, -0.6, -0.1, 0.1, 0.5, 0.7, 1, -0.3, 0.2, 0.6])
>>> np.ediff1d(np.sign(arr), to_begin=0) // 2
array([ 0., 0., 0., 0., 1., 0., 0., 0., -1., 1., 0.])
If you'd like to consider 0
as positive:
>>> arr = np.array([-1, -0.8, -0.6, -0.1, 0.0, 0.5, 0.7, 1, -0.3, 0.2, 0.6])
>>> np.ediff1d(np.where(arr==0, 1, np.sign(arr)), to_begin=0)//2
array([ 0., 0., 0., 0., 1., 0., 0., 0., -1., 1., 0.])
EDIT
Based on your edit, you can do the following:
>>> arr = [-0.5, -0.8, -0.6, -0.2, 0.2, 0.5, 0.7, 0.9, -0.3, 0.2, 0.6, 0.4, 0, 0.2, 0, -0.3, -0.2, 0, -0.6, 0, 0.3]
>>> output = np.array(arr)
>>> nonzero_idx = output != 0
>>> nonzero_arr = output[nonzero_idx]
>>> res = np.ediff1d(np.sign(nonzero_arr), to_begin=0) // 2
>>> output[nonzero_idx] = res
>>> output
array([ 0., 0., 0., 0., 1., 0., 0., 0., -1., 1., 0., 0., 0.,
0., 0., -1., 0., 0., 0., 0., 1.])
Upvotes: 1
Reputation: 187
The answer provided by Cyttorak is correct and a lot prettier than mine, however, if you don't mind a little bit uglier code and want speed, this is faster.
a2 = np.array([-1, 1])
array = np.array([-1, -0.8, -0.6, -0.1, 0.1, 0.5, 0.7, 1, -0.3, 0.2, 0.6])
array = np.where(array >= 0, -1, 1)
output = np.convolve(array, a2, mode='same')
output = np.where((output == 2) | (output == -2), output, 0) // 2
Edit: sorry, forgot to copy-paste a2 :D
Upvotes: 0