Numpy“哪里”功能无法避免评估Sqrt(负)

时间:2018-10-03 07:45:33

标签: python numpy

似乎np.where函数先评估所有可能的结果,然后再评估条件。这意味着,就我而言,即使以后不再使用,它​​也会求出-5,-4,-3,-2,-1的平方根。

我的代码运行并运行。但是我的问题是警告。我避免使用循环来评估每个元素,因为它的运行速度比np.where慢得多。

所以,我在这里问

  1. 有什么方法可以让np.where首先评估条件吗?
  2. 我可以仅关闭此特定警告吗?怎么样?
  3. 如果有更好的建议,另一种更好的方法。

这里只有一个简短的示例代码,与我的真实代码相对应,这是巨大的。但是本质上有同样的问题。

输入:

import numpy as np

c=np.arange(10)-5
d=np.where(c>=0, np.sqrt(c) ,c )

输出:

RuntimeWarning: invalid value encountered in sqrt
d=np.where(c>=0,np.sqrt(c),c)

4 个答案:

答案 0 :(得分:6)

有一个很多更好的方法可以做到这一点。让我们看看您的代码在做什么,看看为什么。

np.where接受三个数组作为输入。数组不支持惰性评估。

d = np.where(c >= 0, np.sqrt(c), c)

因此,此行等效于

a = (c >= 0)
b = np.sqrt(c)
d = np.where(a, b, c)

请注意,输入是在where被调用之前立即计算的。

幸运的是,您根本不需要使用where。相反,只需使用布尔掩码:

mask = (c >= 0)
d = np.empty_like(c)
d[mask] = np.sqrt(c[mask])
d[~mask] = c[~mask]

如果您期望很多负面因素,则可以复制所有元素,而不仅仅是负面因素:

d = c.copy()
d[mask] = np.sqrt(c[mask])

一个更好的解决方案可能是使用掩码数组:

d = np.ma(c, c < 0)
d = np.ma.sqrt(d)

要访问整个数据数组,而未更改被屏蔽的部分,请使用d.data

答案 1 :(得分:1)

这是您第二个问题的答案。

是的,您可以关闭警告。使用warnings模块。

import warnings
warnings.filterwarnings("ignore")

答案 2 :(得分:1)

一种解决方案是不使用np.where,而改用索引。

c = np.arange(10)-5
d = c.copy()
c_positive = c > 0
d[c_positive] = np.sqrt(c[c_positive])

答案 3 :(得分:0)

np.sqrtufunc,并接受where参数。在这种情况下,它可以用作遮罩:

In [61]: c = np.arange(10)-5.0
In [62]: d = c.copy()
In [63]: np.sqrt(c, where=c>=0, out=d);
In [64]: d
Out[64]: 
array([-5.        , -4.        , -3.        , -2.        , -1.        ,
        0.        ,  1.        ,  1.41421356,  1.73205081,  2.        ])

np.where情况相反,这不会在〜where元素处评估函数。