1

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.]
2
  • Have you checked (Numbers<=0).argmax() by itself? If that isn't right, the larger expression won't be either. Commented Feb 16, 2021 at 23:49
  • np.ones(3, bool).argmax() is 0, the first True. Commented Feb 17, 2021 at 0:02

2 Answers 2

2

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 -

  1. 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.

  2. 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 ~

  3. 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 -

  1. With a value that meets condition
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. ])
  1. With no values meeting the condition
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. ])
Sign up to request clarification or add additional context in comments.

5 Comments

More efficiently, n[np.logical_or.accumulate(n >= 0)] = 0
Thank you that works. Is there a way I could implement this so that it also scans another array like np.where(~(Numbers2<=0).cumsum().astype(bool), Numbers, 0) where Numbers2 is another array like Numbers with the same length but for the numbers below 0 it just modifies Numbers elements to 0. `
Wouldnt the same code work for that as well? np.where(~(Numbers2<=0).cumsum().astype(bool), Numbers, 0)?
Working for me. I have edited my answer do check.
Thank you i did a stupid mistake thank you it works
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.