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

ppa*_*ler 5 python numpy

我正在尝试用默认值替换低于和高于阈值的“坏值”(例如将它们设置为 NaN)。 \n我正在取消具有 1000k 值及更多值的 numpy 数组 - 因此性能是一个问题。

\n\n

我的原型分两步进行操作,是否可以一步完成此操作?

\n\n
import numpy as np\n\ndata = np.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])\n\nupper_threshold = 7\nlower_threshold = 1\ndefault_value = np.NaN\n\n# is it possible to do this in one expression?\ndata[data > upper_threshold] = default_value\ndata[data < lower_threshold] = default_value\n\nprint data # [ nan   1.   2.   3.   4.   5.   6.   7.  nan  nan]\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如这个相关问题中所评论的(用上限和下限替换列表值的Pythonic way(钳制、剪裁、阈值处理)?

\n\n
\n

与许多其他函数一样,np.clip 是 python 的,但它遵循 arr.clip 方法。对于常规数组,该方法是编译的,因此速度会更快(大约 2 倍)。\xe2\x80\x93 hpaulj

\n
\n\n

我也希望能找到更快的方法,先谢谢了!

\n

Div*_*kar 3

boolean-indexing与组合面膜一起使用-

data[(data > upper_threshold) | (data < lower_threshold)] = default_value
Run Code Online (Sandbox Code Playgroud)

运行时测试 -

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
Run Code Online (Sandbox Code Playgroud)

看起来我们使用所提出的方法并没有表现得更好one-pass-indexing。原因可能是OR-ing掩码的计算比直接使用布尔索引本身赋值要昂贵一些。