如果numpy数组元素超过特定阈值,则将其设为零

79

假设我有一个包含10个元素的numpy数组,例如:

a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])

现在我想要高效地将所有大于10a 值设为0,得到:

[2, 0, 0, 7, 9, 0, 0, 0, 5, 3]

因为我目前使用的是循环(for loop),速度非常慢:

# Zero values below "threshold value".
def flat_values(sig, tv):
    """
    :param sig: signal.
    :param tv: threshold value.
    :return:
    """
    for i in np.arange(np.size(sig)):
        if sig[i] < tv:
            sig[i] = 0
    return sig

如何在考虑到包含10^6个元素的大数组的情况下,以最高效的方式实现这一点?

4个回答

169
In [7]: a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])

In [8]: a[a > 10] = 0

In [9]: a
Out[9]: array([2, 0, 0, 7, 9, 0, 0, 0, 5, 3])

5
完美的回答。请注意如果您关心元素的绝对值,可以使用:a[np.abs(a) > 10] = 0 - Dylan Hogg
1
有没有一种方法可以组合多个(比如5个)条件语句? - Bryson S.
7
@BrysonS。编写一个包含5个条件语句并返回布尔值的单独函数。然后您可以像这样使用它:a[my_validation_func(a)] = 0 - Alex Hall
@AlexHall,你能展示一下 my_validation_func(a) 的返回值是什么样子的吗? - Bruno Pessanha

64

通常情况下,在Python中,列表推导比for循环更快(因为Python知道它不需要关心在常规的for循环中可能发生的许多事情):

a = [0 if a_ > thresh else a_ for a_ in a]

但是正如@unutbu正确指出的,NumPy允许列表索引和逐元素比较,从而给你索引列表,因此:

super_threshold_indices = a > thresh
a[super_threshold_indices] = 0

希望能更快。

一般来说,在对数据向量应用方法时,可以查看 numpy.ufuncs,它们通常比使用任何本地机制映射的 Python 函数执行得更快。


1
你的语句需要一个else: a = [0 if a_ > thresh else a_ for a_ in a] - ben26941
@ben26941 确实如此。嗯,令人惊讶的是到目前为止没有人注意到。 - Marcus Müller
有关非破坏性操作,请参见 abda01 - mins

27

如果您不想更改原始数组

In [2]: a = np.array([2, 23, 15, 7, 9, 11, 17, 19, 5, 3])
      
In [3]: b = np.where(a > 10, 0, a)

In [4]: b
Out[4]: array([2, 0, 0, 7, 9, 0, 0, 0, 5, 3])

In [5]: a
Out[5]: array([ 2, 23, 15,  7,  9, 11, 17, 19,  5,  3])

1
从sentdex在Youtube上的神经网络系列中,他使用np.maximum(0,[your array])将所有小于0的值变为0。
对于你的问题,我尝试了np.minimum(10,[your array]),它似乎非常快。我甚至在一个大小为10e6的数组上进行了操作(使用50 * np.random.rand(10000000)生成均匀分布),并且仅用了0.039571秒。我希望这足够快了。

这将把它们替换为10,而不是0。 - Jacob R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接