Sitemap
1 min readMar 11, 2023

You say:

e1[e1>5] = e1*10 might seem only sensible. But it simply doesn’t work.

Of course the reason it doesn't work is that the two sides are of different lengths. You *can* write:

e1[e1>5] = e1[e1>5]*10

While this is slightly unfortunate in requiring e1 to be indexed twice by the boolean ndarray e1 > 5, it avoids what to me is the most unfortunate quality of np.where(), namely that both the 'true' and 'false' values are evaluated for every element. In your case, it's a trivial matter of performing 10 multiplications instead of 5, but in real life there are often situations where, for instance, the 'true' side (the second argument of where()) cannot be evaluated for those elements for which the test returns False. Consider, for example, taking the square root of only the positive elements of an array:

>>> s = np.array([4, 9, -25, 100])

>>> s = np.where(s>=0, np.sqrt(s), s)

This gives the error "invalid value encountered in sqrt", whereas this works:

>>> s[s>=0] = np.sqrt(s[s>=0])

Of course you can modify the expression to provide some kind of protection against domain errors, such as:

>>> s = np.where(s>=0, np.sqrt(np.abs(s)), s)

This works because the unwanted sqrt(+25) is discarded by the where() condition. However

this approach rapidly becomes unfun if both the 'true' and 'false' sides are complicated expressions.

Really, this is a place where masked arrays should come into play.

--