Python 如何用除零返回0
我试图在python中执行元素级除法,但是如果遇到零,我需要商为零 例如:Python 如何用除零返回0,python,arrays,numpy,error-handling,divide-by-zero,Python,Arrays,Numpy,Error Handling,Divide By Zero,我试图在python中执行元素级除法,但是如果遇到零,我需要商为零 例如: array1 = np.array([0, 1, 2]) array2 = np.array([0, 1, 1]) array1 / array2 # should be np.array([0, 1, 2]) 我总是可以在数据中使用for循环,但要真正利用numpy的优化,我需要divide函数在除以零的错误时返回0,而不是忽略错误 除非我遗漏了什么,否则它似乎无法在出现错误时返回值。对于如何在设置自己的除以零错误
array1 = np.array([0, 1, 2])
array2 = np.array([0, 1, 1])
array1 / array2 # should be np.array([0, 1, 2])
我总是可以在数据中使用for循环,但要真正利用numpy的优化,我需要divide函数在除以零的错误时返回0,而不是忽略错误
除非我遗漏了什么,否则它似乎无法在出现错误时返回值。对于如何在设置自己的除以零错误处理的同时充分利用numpy,有谁有其他建议吗?尝试分两步进行。先除法,然后替换
with numpy.errstate(divide='ignore'):
result = numerator / denominator
result[denominator == 0] = 0
numpy.errstate
行是可选的,它只是防止numpy告诉您被零除的“错误”,因为您已经打算这样做,并处理该情况。您也可以基于inf
进行替换,前提是数组数据类型是浮动的,如下所示:
我在搜索相关问题时发现的一个答案是根据分母是否为零来操纵输出 假设
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,此操作将起到一定作用。在其他答案的基础上进一步完善:
0/0
通过将invalid='ignore'
添加到
- 介绍如何将
np.nan
转换为0
代码:
输出:
c: [ 0. 0. 0. 1. 0.66666667]
基于@Franck Dernoncourt的答案,修复了-1/0和我在标量上的错误:
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
在numpy v1.7+中,您可以利用的“where”选项。您可以在一行中完成任务,而不必处理errstate上下文管理器
>>> 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'参数中给它的值保持不变。已弃用(PYTHON 2解决方案):
一行(抛出警告)
另一个值得一提的解决方案是:
>>> 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.])
您可能应该在上下文np.errstate(divide='ignore'):
@WarrenWeckesser Fair point中执行除法。我编辑了答案以包含上下文divide='warn'
如果他/她仍然希望得到通知,也可能很有用。检查0/0
以及1/0
错误的工作做得很好。我用中给出的示例数组尝试了您的方法,结果似乎是非常高的数字,而不是np.inf,这仍然是最终结果。这会阻碍这种方法。如果a
或b
包含NaN
,您的解决方案会突然给出0
。这很容易隐藏代码中的错误,这是绝对意外的numpy.nan_to_num(x,copy=True,nan=0.0,posinf=None,neginf=None)
是签名。谢谢,我甚至没有用@Frank Dernoncourt的代码发现这个bug。嗨,我正在尝试做数组数学,我希望0/0得到0,但我也希望在计算中忽略np.nan。这样行吗?同时,我也在努力理解。c[~np.isfinite(c)]=0做什么?我从未在python中使用~。这是干什么用的?感谢you@user20408,~
在numpy数组中反转True
和False
:print~np.array([True,False,False])
c[~np.isfinite(c)]=0
表示:找到c
有限的位置,用~
将这些位置反转为非有限,并将非有限值设置为0。另请参见“在我的python版本(python 2.7.11 | Continuum Analytics,Inc.)中,这正是您得到的输出。带有警告。最简洁正确的答案是,如果a
和/或b
可能是整数数组,那么这是相同的概念,您只需显式设置正确的输出类型:c=np.divide(a,b,out=np.zeros(a.shape,dtype=float),其中=b!=0)
out=np.zeros\u like(a)
是关键的,如注释行中所述。如果我使用np.divide(a,b,out=np.zeros\u like(a),其中=b!=0)
,我得到了错误分配给函数调用,而函数调用不返回
。奇怪的是,我使用了两次,错误只弹出一次。如果有人对哪一个最快感兴趣,这个方法比@denis/@Franck Dernoncourt的答案快,运行一百万个周期,我得到的是8秒,而不是11秒这一行应该是indZeros=np。其中(arrayB=0)除以零(令人困惑,因为它不正确!)在numpy中给出inf
,而不是undefined或nan
。因此这将设置为除零,而不是像人们可能期望的那样和OP所要求的那样设置为0
。您可以通过设置posinf=0
来解决这个问题。啊,是的,这个答案太旧了,代码在Python 2中(在那里工作)。
>>> 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]
np.nan_to_num(array1 / array2)
>>> 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.])