问题:如何用零除返回0
我正在尝试在python中执行元素明智的除法,但是如果遇到零,我需要将商设为零。
例如:
array1 = np.array([0, 1, 2])
array2 = np.array([0, 1, 1])
array1 / array2 # should be np.array([0, 1, 2])
我总是可以在数据中使用for循环,但是要真正利用numpy的优化,我需要除法函数在除以零错误后返回0,而不是忽略错误。
除非我缺少任何东西,否则numpy.seterr()似乎不会在出现错误时返回值。在设置自己的除以零的错误处理方法时,还有人对我如何从numpy中获得最大收益有其他建议吗?
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?
回答 0
在numpy v1.7 +中,您可以利用ufuncs的“ where”选项。您可以一行完成事情,而不必与错误上下文管理器打交道。
>>> 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]
在这种情况下,它将在“其中” b不等于零的任何地方进行除法计算。当b等于零时,它与您在’out’参数中最初给它的任何值保持不变。
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.
回答 1
以@Franck Dernoncourt的答案为基础,修正-1 / 0:
def div0( a, b ):
""" ignore / 0, div0( [-1, 0, 1], 0 ) -> [0, 0, 0] """
with np.errstate(divide='ignore', invalid='ignore'):
c = np.true_divide( a, b )
c[ ~ np.isfinite( c )] = 0 # -inf inf NaN
return c
div0( [-1, 0, 1], 0 )
array([0, 0, 0])
Building on @Franck Dernoncourt’s answer, fixing -1 / 0:
def div0( a, b ):
""" ignore / 0, div0( [-1, 0, 1], 0 ) -> [0, 0, 0] """
with np.errstate(divide='ignore', invalid='ignore'):
c = np.true_divide( a, b )
c[ ~ np.isfinite( c )] = 0 # -inf inf NaN
return c
div0( [-1, 0, 1], 0 )
array([0, 0, 0])
回答 2
以其他答案为基础,并在以下方面进行改进:
码:
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))
输出:
c: [ 0. 0. 0. 1. 0.66666667]
Building on the other answers, and improving on:
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]
回答 3
单线(引发警告)
np.nan_to_num(array1 / array2)
One-liner (throws warning)
np.nan_to_num(array1 / array2)
回答 4
尝试分两个步骤进行。先划分,然后更换。
with numpy.errstate(divide='ignore'):
result = numerator / denominator
result[denominator == 0] = 0
该numpy.errstate
行是可选的,并且仅防止numpy告诉您除零的“错误”,因为您已经打算这样做并处理这种情况。
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.
回答 5
您也可以inf
仅根据数组dtypes为float来基于进行替换,如下所示:
>>> 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.])
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.])
回答 6
我发现搜索一个相关问题的一个答案是根据分母是否为零来操纵输出。
假设arrayA
和arrayB
已经初始化,但是arrayB
有一些零。如果我们要arrayC = arrayA / arrayB
安全地进行计算,可以执行以下操作。
在这种情况下,只要我在其中一个单元格中myOwnValue
被零除,就将单元格设置为等于,在这种情况下为零
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
脚注:回想起来,这条线无论如何都是不必要的,因为它arrayC[i]
被实例化为零。但是,如果是这种情况myOwnValue != 0
,该操作将有所作为。
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.
回答 7
另一个值得一提的解决方案:
>>> 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.])
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.])