我正在尝试用默认值替换阈值以下和上方的"错误值"(例如将它们设置为 NaN)。我正在取消一个具有 1000k 值及更多值的 numpy 数组 - 所以性能是一个问题。
我的原型分两步完成操作,是否有一个步骤完成此操作的可知性?
import numpy as np
data = np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
upper_threshold = 7
lower_threshold = 1
default_value = np.NaN
# is it possible to do this in one expression?
data[data > upper_threshold] = default_value
data[data < lower_threshold] = default_value
print data # [ nan 1. 2. 3. 4. 5. 6. 7. nan nan]
正如这个相关问题中所评论的(Pythonic 用上限和下限替换列表值的方法(钳位、裁剪、阈值)?
像许多其他函数一样,np.clip是python,但它服从arr.clip,该方法。对于常规数组,该方法被编译,因此会更快(大约 2 倍)。- 保尔
我也希望能找到更快的方法,提前谢谢!
组合面具一次性使用boolean-indexing
-
data[(data > upper_threshold) | (data < lower_threshold)] = default_value
运行时测试 -
In [109]: def onepass(data, upper_threshold, lower_threshold, default_value):
...: mask = (data > upper_threshold) | (data < lower_threshold)
...: data[mask] = default_value
...:
...: def twopass(data, upper_threshold, lower_threshold, default_value):
...: data[data > upper_threshold] = default_value
...: data[data < lower_threshold] = default_value
...:
In [110]: upper_threshold = 7
...: lower_threshold = 1
...: default_value = np.NaN
...:
In [111]: data = np.random.randint(-4,11,(1000000)).astype(float)
In [112]: %timeit twopass(data, upper_threshold, lower_threshold, default_value)
100 loops, best of 3: 2.41 ms per loop
In [113]: data = np.random.randint(-4,11,(1000000)).astype(float)
In [114]: %timeit onepass(data, upper_threshold, lower_threshold, default_value)
100 loops, best of 3: 2.74 ms per loop
看起来我们使用提议的one-pass-indexing
方法的表现并没有更好。原因可能是掩码OR-ing
的计算比直接使用布尔索引本身分配值要昂贵一些。