要在以下代码中计算b
,elif
语句仅在前一个if
语句返回False
时运行
我的第一个问题是关于c
。我们是否可以调整第二个where
比较,使其仅在第一个where
比较为False
的a_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))