ege Selcuk
ege Selcuk

Reputation: 237

Array formatting with argmax numpy Python

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

Answers (2)

Akshay Sehgal
Akshay Sehgal

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 -

  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. ])

Upvotes: 2

Jan Christoph Terasa
Jan Christoph Terasa

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

Related Questions