Reputation: 237
I am having trouble with the Numbers[(Numbers<=0).argmax():] = 0
function it is supposed to turn all the elements behind it into zeroes if the condition is met, however if the condition is not met it turns all the array elements into zeroes. How can i fix this issue. If the Numbers<=0
condition is not met the array should not change.
Array with satisfying condition at -35.15610151:
Numbers = np.array([123.6, 123.6 , 123.6, 110.3748, 111.6992976,
102.3165566, 97.81462811 , 89.50038472 , 96.48141473 , 90.49956702,
88.59907611 , 77.96718698, 61.51611052, 56.84088612, 55.36302309,
54.69866681, 56.44902415 , 59.49727145, 42.12406819, 27.42276839,
33.86711896, 32.10602877, -35.15610151, 32.34361339 , 29.20628289])
Numbers[(Numbers<=0).argmax():] = 0
Output:
[123.6 123.6 123.6 110.3748 111.6992976
102.3165566 97.81462811 89.50038472 96.48141473 90.49956702
88.59907611 77.96718698 61.51611052 56.84088612 55.36302309
54.69866681 56.44902415 59.49727145 42.12406819 27.42276839
33.86711896 32.10602877 0. 0. 0. ]
Array with no satisfying condition, turned -35.15610151 into +35.15610151:
Numbers = np.array([123.6, 123.6 , 123.6, 110.3748, 111.6992976,
102.3165566, 97.81462811 , 89.50038472 , 96.48141473 , 90.49956702,
88.59907611 , 77.96718698, 61.51611052, 56.84088612, 55.36302309,
54.69866681, 56.44902415 , 59.49727145, 42.12406819, 27.42276839,
33.86711896, 32.10602877, 35.15610151, 32.34361339 , 29.20628289])
Numbers[(Numbers<=0).argmax():] = 0
Output:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.]
Upvotes: 1
Views: 65
Reputation: 19322
Try these 2 methods, one is in place assignment to the NumPy view and the other creates a fresh array to be assigned to another variable -
#Method 1 (Inplace assignment)
Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0
Or,
#Method 2 (Not inplace)
np.where(~(Numbers<=0).cumsum(dtype=bool), Numbers, 0)
Or,
#As an excellent suggestion by Mad Physicist!
Numbers[np.logical_or.accumulate(Numbers >= 0)] = 0
Explanation -
The bool array that returns [F, F, F, T, F, F, F]
can be seen as an array of 1s and 0s. Doing a cumsum ends up propogating the first T to the subsequent elements.
This, therefore, turns the array as [F, F, F, T, T, T, T]
which can now be used with just boolean indexing
and set the view to 0 OR np.where
to fetch original elements or 0 based on reversing the boolean with ~
Advantage here is that if your array is just composed of False, meaning no element meets the condition, it just returns the original Numbers
itself, instead of setting them to 0.
Running tests -
Numbers = np.array([123.6 , 123.6 , -123.6, 110.3748 , 111.6992976, 102.3165566, 97.81462811])
Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0
#array([123.6, 123.6, 0. , 0. , 0. , 0. , 0. ])
Numbers = np.array([123.6 , 123.6 , 123.6, 110.3748 , 111.6992976, 102.3165566, 97.81462811])
Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0
#array([123.6 , 123.6 , 123.6 , 110.3748 ,111.6992976 , 102.3165566 , 97.81462811])
EDIT: New scenario as requested
Numbers1 = np.array([1.1, 2.2, 3.3, 4.4, 5.5])
Numbers2 = np.array([1,2,-3,4,5])
Numbers2 = np.where(~(Numbers2<=0).cumsum().astype(bool), Numbers1, 0)
Numbers2
array([1.1, 2.2, 0. , 0. , 0. ])
Upvotes: 2
Reputation: 5935
Just use an if
for this, it represents the intention quite well, and is easy to understand:
smaller_equal_zero = Numbers <= 0
if smaller_equal_zero.any():
Numbers[smaller_equal_zero.argmax():] = 0
With Python 3.8+ you can use an assignment expression in the if
:
if (smaller_equal_zero := Numbers <= 0).any():
Numbers[smaller_equal_zero.argmax():] = 0
Upvotes: 0