将高于和低于阈值的列表值替换为 python 中的默认值



我正在尝试用默认值替换阈值以下和上方的"错误值"(例如将它们设置为 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的计算比直接使用布尔索引本身分配值要昂贵一些。

最新更新