Arman Mojaver
Arman Mojaver

Reputation: 451

Modify values of a numpy array based on a condition

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

Answers (2)

Sayandip Dutta
Sayandip Dutta

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

Terra
Terra

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

Related Questions