似乎np.where
函数先评估所有可能的结果,然后再评估条件。这意味着,就我而言,即使以后不再使用,它也会求出-5,-4,-3,-2,-1的平方根。
我的代码运行并运行。但是我的问题是警告。我避免使用循环来评估每个元素,因为它的运行速度比np.where
慢得多。
所以,我在这里问
np.where
首先评估条件吗?这里只有一个简短的示例代码,与我的真实代码相对应,这是巨大的。但是本质上有同样的问题。
输入:
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)
答案 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)
答案 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.sqrt
是ufunc
,并接受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元素处评估函数。