使用python 2.7,scipy 1.0.0-3
显然,我对如何操作函数或者操作中存在已知错误的numpy有误解。我希望有人可以告诉我哪些并解释一个解决方法来抑制我试图避免的恼人警告。当我使用pandas Series where()。
时,我会得到相同的行为为了简单起见,我将使用一个numpy数组作为我的例子。假设我想在数组上应用np.log(),只有这样,条件值才是有效输入,即myArray> 0.0。对于不应用此函数的值,我想设置输出标志-999.9:
myArray = np.array([1.0, 0.75, 0.5, 0.25, 0.0])
np.where(myArray>0.0, np.log(myArray), -999.9)
我希望numpy.where()不要抱怨数组中的0.0值,因为条件在那里是False,但它确实执行并且它似乎实际执行了该False条件:
-c:2: RuntimeWarning: divide by zero encountered in log
array([ 0.00000000e+00, -2.87682072e-01, -6.93147181e-01,
-1.38629436e+00, -9.99900000e+02])
如果给出x和y并且输入数组是1-D,则其等效于: [xv if c else yv for(c,xv,yv)in zip(condition,x,y)]
我希望与此声明不同,因为
[np.log(val) if val>0.0 else -999.9 for val in myArray]
根本不提供任何警告:
[0.0, -0.2876820724517809, -0.69314718055994529, -1.3862943611198906, -999.9]
那么,这是一个已知的错误吗?我不想压制整个代码的警告。
答案 0 :(得分:3)
您只能使用其可选的log
参数
where
np.where(myArray>0.0, np.log(myArray, where=myArray>0.0), -999.9)
或更有效率
mask = myArray > 0.0
np.where(mask, np.log(myArray, where=mask), -999)
或者如果你发现“双处”丑陋
np.log(myArray, where=myArray>0.0, out=np.full(myArray.shape, -999.9))
这三者中的任何一个都应该禁止警告。
答案 1 :(得分:2)
鉴于对Python的基本了解,where
的这种行为应该是可以理解的。这是一个Python表达式,它使用了几个numpy
函数。
这个表达式会发生什么?
np.where(myArray>0.0, np.log(myArray), -999.9)
解释器首先计算函数的所有参数,然后将结果传递给where
。那么有效:
cond = myArray>0.0
A = np.log(myArray)
B = -999.9
np.where(cond, A, B)
警告在第2行产生,而不是在第4行产生。
第4行相当于:
[xv if c else yv for (c,xv,yv) in zip(cond, A, B)]
或
[A[i] if c else B for i,c in enumerate(cond)]
np.where
最常用于一个参数,它是np.nonzero
的同义词。我们没有看到这种经常在SO上的三种形式的形式。它不是很有用,部分原因是因为它不会节省计算费用。
屏蔽分配更常见,特别是如果有两个以上的选择。
In [123]: mask = myArray>0
In [124]: out = np.full(myArray.shape, np.nan)
In [125]: out[mask] = np.log(myArray[mask])
In [126]: out
Out[126]: array([ 0. , -0.28768207, -0.69314718, -1.38629436, nan])
Paul Panzer展示了如何对where
的{{1}}参数执行相同操作。该功能并未尽可能多地使用。
log
答案 2 :(得分:1)
这不是错误。有关类似问题,请参阅this related answer。文档中的示例具有误导性,但该答案将详细介绍它。
问题在于,解释器在编译时处理三元语句,而numpy.where
是常规函数。因此,三元语句允许短路,而在事先定义参数时这是不可能的。
换句话说,{<1}}的参数是在处理布尔数组之前计算的。
您可能认为这是低效的:为什么要构建2个独立的数组,然后使用第3个布尔数组来决定选择哪个项目?当然这是工作的两倍/内存的两倍?
然而,这种低效率不仅仅是由作用于整个阵列的numpy.where
函数提供的矢量化所抵消,例如: numpy
。
考虑文档中提供的示例:
如果给出
np.log(arr)
和x
且输入数组是1-D,则y
为 相当于::where
注意输入是数组。尝试运行:
[xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
你会注意到这个错误。