Reputation: 22260
I'm trying to perform an element wise divide in python, but if a zero is encountered, I need the quotient to just be zero.
For example:
array1 = np.array([0, 1, 2])
array2 = np.array([0, 1, 1])
array1 / array2 # should be np.array([0, 1, 2])
I could always just use a for-loop through my data, but to really utilize numpy's optimizations, I need the divide function to return 0 upon divide by zero errors instead of ignoring the error.
Unless I'm missing something, it doesn't seem numpy.seterr() can return values upon errors. Does anyone have any other suggestions on how I could get the best out of numpy while setting my own divide by zero error handling?
Upvotes: 184
Views: 200400
Reputation: 21
A solution with try/except to manage any kind of those numpy RuntimeWarnings:
with np.errstate(all='raise'):
try:
array3 = array1/array2
except:
array3 = array1 # Give whatever default value you like
Upvotes: 0
Reputation: 21947
Building on @Franck Dernoncourt's answer, fixing -1 / 0 and my bug on scalars:
def div0( a, b, fill=np.nan ):
""" a / b, divide by 0 -> `fill`
div0( [-1, 0, 1], 0, fill=np.nan) -> [nan nan nan]
div0( 1, 0, fill=np.inf ) -> inf
"""
with np.errstate(divide='ignore', invalid='ignore'):
c = np.true_divide( a, b )
if np.isscalar( c ):
return c if np.isfinite( c ) \
else fill
else:
c[ ~ np.isfinite( c )] = fill
return c
Upvotes: 58
Reputation: 8608
One-liner (throws warning)
np.nan_to_num(array1 / array2)
Upvotes: 20
Reputation: 104
An other solution worth mentioning :
>>> a = np.array([1,2,3], dtype='float')
>>> b = np.array([0,1,3], dtype='float')
>>> b_inv = np.array([1/i if i!=0 else 0 for i in b])
>>> a*b_inv
array([0., 2., 1.])
Upvotes: -1
Reputation: 4319
In numpy v1.7+, you can take advantage of the "where" option for ufuncs. You can do things in one line and you don't have to deal with the errstate context manager.
>>> a = np.array([-1, 0, 1, 2, 3], dtype=float)
>>> b = np.array([ 0, 0, 0, 2, 2], dtype=float)
# If you don't pass `out` the indices where (b == 0) will be uninitialized!
>>> c = np.divide(a, b, out=np.zeros_like(a), where=b!=0)
>>> print(c)
[ 0. 0. 0. 1. 1.5]
In this case, it does the divide calculation anywhere 'where' b does not equal zero. When b does equal zero, then it remains unchanged from whatever value you originally gave it in the 'out' argument.
Upvotes: 356
Reputation: 83167
Building on the other answers, and improving on:
0/0
handling by adding invalid='ignore'
to numpy.errstate()
numpy.nan_to_num()
to convert np.nan
to 0
.Code:
import numpy as np
a = np.array([0,0,1,1,2], dtype='float')
b = np.array([0,1,0,1,3], dtype='float')
with np.errstate(divide='ignore', invalid='ignore'):
c = np.true_divide(a,b)
c[c == np.inf] = 0
c = np.nan_to_num(c)
print('c: {0}'.format(c))
Output:
c: [ 0. 0. 0. 1. 0.66666667]
Upvotes: 54
Reputation: 4674
Try doing it in two steps. Division first, then replace.
with numpy.errstate(divide='ignore'):
result = numerator / denominator
result[denominator == 0] = 0
The numpy.errstate
line is optional, and just prevents numpy from telling you about the "error" of dividing by zero, since you're already intending to do so, and handling that case.
Upvotes: 17
Reputation: 22260
One answer I found searching a related question was to manipulate the output based upon whether the denominator was zero or not.
Suppose arrayA
and arrayB
have been initialized, but arrayB
has some zeros. We could do the following if we want to compute arrayC = arrayA / arrayB
safely.
In this case, whenever I have a divide by zero in one of the cells, I set the cell to be equal to myOwnValue
, which in this case would be zero
myOwnValue = 0
arrayC = np.zeros(arrayA.shape())
indNonZeros = np.where(arrayB != 0)
indZeros = np.where(arrayB = 0)
# division in two steps: first with nonzero cells, and then zero cells
arrayC[indNonZeros] = arrayA[indNonZeros] / arrayB[indNonZeros]
arrayC[indZeros] = myOwnValue # Look at footnote
Footnote: In retrospect, this line is unnecessary anyways, since arrayC[i]
is instantiated to zero. But if were the case that myOwnValue != 0
, this operation would do something.
Upvotes: 0
Reputation: 31040
You can also replace based on inf
, only if the array dtypes are floats, as per this answer:
>>> a = np.array([1,2,3], dtype='float')
>>> b = np.array([0,1,3], dtype='float')
>>> c = a / b
>>> c
array([ inf, 2., 1.])
>>> c[c == np.inf] = 0
>>> c
array([ 0., 2., 1.])
Upvotes: 3