Numpy在哪里划分为零

时间:2018-02-08 23:14:51

标签: python numpy

我需要按以下方式计算x(遗留代码):

x = numpy.where(b == 0, a, 1/b) 

我认为它适用于(就像在代码中一样),但它在中无效(if b = 0它会返回错误)。

如何在python-3.x中使其工作?

编辑:错误消息(Python 3.6.3):

ZeroDivisionError: division by zero

5 个答案:

答案 0 :(得分:9)

numpy.where不是条件执行;它是有条件的选择。在函数调用之前总是完全评估Python函数参数,因此函数无法有条件地或部分地评估其参数。

您的代码:

x = numpy.where(b == 0, a, 1/b)

告诉Python反转 b的每个元素,然后根据a的元素从1/bb == 0中选择元素。 Python甚至没有达到选择元素的程度,因为计算1/b失败了。

您只需反转b的非零部分即可避免此问题。假设ab具有相同的形状,它可能如下所示:

x = numpy.empty_like(b)
mask = (b == 0)
x[mask] = a[mask]
x[~mask] = 1/b[~mask]

答案 1 :(得分:4)

处理数组除法中0个元素的一个老技巧是添加一个条件值:

In [63]: 1/(b+(b==0))
Out[63]: array([1.        , 1.        , 0.5       , 0.33333333])

(我多年前在apl)中使用过。

x = numpy.where(b == 0, a, 1/b)的评估方式与任何其他Python函数的评估方式相同。评估每个函数参数,并将值传递给where函数。没有'短路'或绕过1/b的错误值的其他方法。

因此,如果1/b返回错误,您需要更改b,以便它不会这样做,在陷阱陷阱ZeroDivisionError的上下文中计算它,或者跳过1/b

In [53]: 1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-53-9e1622b385b6> in <module>()
----> 1 1/0

ZeroDivisionError: division by zero
In [54]: 1.0/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-54-99b9b9983fe8> in <module>()
----> 1 1.0/0

ZeroDivisionError: float division by zero
In [55]: 1/np.array(0)
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
  #!/usr/bin/python3
Out[55]: inf

什么是ab?标量,某种规模的数组?

如果where(也许b)是一个数组,

a最有意义:

In [59]: b = np.array([0,1,2,3])

裸师给我一个警告,并inf元素:

In [60]: 1/b
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
  #!/usr/bin/python3
Out[60]: array([       inf, 1.        , 0.5       , 0.33333333])

我可以使用whereinf替换为其他内容,例如nan

In [61]: np.where(b==0, np.nan, 1/b)
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
  #!/usr/bin/python3
Out[61]: array([       nan, 1.        , 0.5       , 0.33333333])

警告可以在@donkopotamus显示时静音。

seterr上下文中errstate的替代with

In [64]: with np.errstate(divide='ignore'):
    ...:     x = np.where(b==0, np.nan, 1/b)
    ...:     
In [65]: x
Out[65]: array([       nan, 1.        , 0.5       , 0.33333333])

How to suppress the error message when dividing 0 by 0 using np.divide (alongside other floats)?

答案 2 :(得分:1)

如果您希望在除以零时禁用numpy中的警告,请执行以下操作:

>>> existing = numpy.seterr(divide="ignore")
>>> # now divide by zero in numpy raises no sort of exception
>>> 1 / numpy.zeros( (2, 2) )
array([[ inf,  inf],
       [ inf,  inf]])
>>> numpy.seterr(*existing)

当然,这只能在数组中控制除零。在执行简单的1 / 0时,它不会阻止错误。

在您的特定情况下,如果我们希望确保我们的工作是b是标量还是numpy类型,请执行以下操作:

# ignore division by zero in numpy
existing = numpy.seterr(divide="ignore")

# upcast `1.0` to be a numpy type so that numpy division will always occur
x = numpy.where(b == 0, a, numpy.float64(1.0) / b) 

# restore old error settings for numpy
numpy.seterr(*existing) 

答案 3 :(得分:0)

我用这个解决了它:

x = (1/(np.where(b == 0, np.nan, b))).fillna(a) 

答案 4 :(得分:-2)

这是一个有趣的问题。我的代码在python 3.6 / numpy 1.13.1上进行了测试。

numpy.where文档声明:

  

如果给出xy且输入数组为1-D,则where为       相当于::

    [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]

那么为什么你会看到错误?拿这个简单的例子:

c = 0
result = (1 if c==0 else 1/c)
# 1

到目前为止一切顺利。首先检查if c==0,结果为1。代码不会尝试评估1/c。这是因为Python解释器处理 lazy 三元运算符,因此只计算适当的表达式。

现在让我们将其转换为numpy.where方法:

c = 0
result = (xv if c else yv for (c, xv, yv) in zip([c==0], [1], [1/c]))
# ZeroDivisionError

在应用逻辑之前,在评估zip([c==0], [1], [1/c])时会发生错误。无法计算生成器表达式本身。作为一个函数,numpy.where没有,实际上也不能复制Python三元表达式的惰性计算。