I have two numpy arrays a
, b
of the same shape, b
has a few zeros. I would like to set an output array to a / b
where b
is not zero, and a
otherwise. The following works, but yields a warning because a / b
is computed everywhere first.
import numpy
a = numpy.random.rand(4, 5)
b = numpy.random.rand(4, 5)
b[b < 0.3] = 0.0
A = numpy.where(b > 0.0, a / b, a)
/tmp/l.py:7: RuntimeWarning: divide by zero encountered in true_divide
A = numpy.where(b > 0.0, a / b, a)
Filtering the division with a mask
doesn't perserve the shape, so this doesn't work:
import numpy
a = numpy.random.rand(4, 5)
b = numpy.random.rand(4, 5)
b[b < 0.3] = 0.0
mask = b > 0.0
A = numpy.where(mask, a[mask] / b[mask], a)
ValueError: operands could not be broadcast together with shapes (4,5) (14,) (4,5)
Any hints on how to avoid the warning?
In Python, we use a try block that contains a return statement to divide 2 numbers. If there is no division by zero error, then it will return the result. Otherwise, the except line will check if the specified exception name is a match, and then it will execute the code under the except block.
Behavior on division by zero can be changed using seterr. When both x1 and x2 are of an integer type, divide will return integers and throw away the fractional part. Moreover, division by zero always yields zero in integer arithmetic.
Python numpy. zeros() function returns a new array of given shape and type, where the element's value as 0.
The Python "ZeroDivisionError: float division by zero" occurs when we try to divide a floating-point number by 0 . To solve the error, use an if statement to check if the number you are dividing by is not zero, or handle the error in a try/except block.
Simply initialize output array with the fallback values (condition-not-satisfying values) or array and then mask to select the condition-satisfying values to assign -
out = a.copy()
out[mask] /= b[mask]
If you are looking for performance, we can use a modified b
for the division -
out = a / np.where(mask, b, 1)
Going further, super-charge it with numexpr
for this specific case of positive values in b
(>=0) -
import numexpr as ne
out = ne.evaluate('a / (1 - mask + b)')
Code to reproduce the plot:
import perfplot
import numpy
import numexpr
numpy.random.seed(0)
def setup(n):
a = numpy.random.rand(n)
b = numpy.random.rand(n)
b[b < 0.3] = 0.0
mask = b > 0
return a, b, mask
def copy_slash(data):
a, b, mask = data
out = a.copy()
out[mask] /= b[mask]
return out
def copy_divide(data):
a, b, mask = data
out = a.copy()
return numpy.divide(a, b, out=out, where=mask)
def slash_where(data):
a, b, mask = data
return a / numpy.where(mask, b, 1.0)
def numexpr_eval(data):
a, b, mask = data
return numexpr.evaluate('a / (1 - mask + b)')
b = perfplot.bench(
setup=setup,
kernels=[copy_slash, copy_divide, slash_where, numexpr_eval],
n_range=[2 ** k for k in range(24)],
xlabel="n"
)
b.save("out.png")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With