如何使嵌套的numpy"where"表现得像嵌套的if语句?



要在以下代码中计算belif语句仅在前一个if语句返回False时运行

我的第一个问题是关于c。我们是否可以调整第二个where比较,使其仅在第一个where比较为Falsea_abs的那些元素上运行?

我们能做一些类似于第三块代码的事情吗?也就是说,仅对a中第一个条件为False的元素运行第二个条件。

目标是提高大型阵列的执行速度。

import numpy as np
a = np.array([[ 0.1, -0.9, -0.7], 
[-3.0,  0.0,  1.1], 
[ 0.5,  0.19, 0.95]])
# 1st block
def f1(x):
x_abs = np.abs(x)
if   x_abs < 0.2: return 0.0
elif x_abs > 0.8: return np.sign(x)
else:                return x
f1_arr = np.frompyfunc(f1, 1, 1)
b = f1_arr(a)
# 2nd block
a_abs = np.abs(a)
c = np.where(a_abs < 0.2, 0.0,        
np.where(a_abs > 0.8, np.sign(a), 
a))
# 3rd block
a[a_abs < 0.2] = 0.0
a[a_abs > 0.8] = np.sign[a]
In [145]: b
Out[145]: 
array([[0.0, -1.0, -0.7],
[-1.0, 0.0, 1.0],
[0.5, 0.0, 1.0]], dtype=object)

与2个where:结果相同

In [146]: a_abs = np.abs(a)
In [147]: temp = np.where(a_abs<0.2, 0, a)
In [148]: temp = np.where(a_abs>0.8, np.sign(a),a)
In [149]: temp
Out[149]: 
array([[ 0.1 , -1.  , -0.7 ],
[-1.  ,  0.  ,  1.  ],
[ 0.5 ,  0.19,  1.  ]])

需要记住的一点是where不是迭代器where的自变量在传递给函数之前进行求值。这是Python的基本语法。

因此对CCD_ 15和CCD_。此外,对整个阵列评估CCD_ 17。

我们可以构建一个结合两个测试的条件:

In [154]: ~(a_abs<0.2)
Out[154]: 
array([[False,  True,  True],
[ True, False,  True],
[ True, False,  True]])
In [155]: ~(a_abs<0.2)&(a_abs>0.8)
Out[155]: 
array([[False,  True, False],
[ True, False,  True],
[False, False,  True]])

尽管这并没有增加任何内容,因为如果是a_abs>0.8,它也是>0.2:

In [156]: temp = np.where(a_abs<0.2, 0, a)
In [157]: np.where(_155, np.sign(temp), temp)
Out[157]: 
array([[ 0. , -1. , -0.7],
[-1. ,  0. ,  1. ],
[ 0.5,  0. ,  1. ]])

这仍然在对所有阵列上的CCD_ 20进行评估。ufunc确实有它们自己的where,它确实评估所选子集上的函数。因此[148]可以写成:

In [159]: np.sign(temp, where=a_abs>0.8, out=temp)
Out[159]: 
array([[ 0. , -1. , -0.7],
[-1. ,  0. ,  1. ],
[ 0.5,  0. ,  1. ]])

我认为这不节省时间(尽管我还没有做测试(;它在CCD_ 23或CCD_ 24中更有用,其中某些数值会引发错误或警告。

一般来说,编译后的numpy方法不会执行";短路";。它们在整个数组上效果最好,我们接受较小的时间(和内存(损失,以便通过使用编译方法获得更多。如果您想以类似c的迭代方式微调性能,请使用numba之类的工具。

您的第二个块不应该是a_abs而不是a吗?

# 2nd block
a_abs = np.abs(a)
c = np.where(a_abs < 0.2, 0.0,        
np.where(a_abs > 0.8, np.sign(a_abs), 
a_abs))

最新更新