如何对NumPy数组执行逐元素布尔运算

89 投票
4 回答
141403 浏览
提问于 2025-04-17 09:00

比如,我想创建一个遮罩,遮住值在40到60之间的元素:

foo = np.asanyarray(range(100))
mask = (foo < 40).__or__(foo > 60)

这样写看起来就很丑。我不能写

(foo < 40) or (foo > 60)

因为最后的结果是:

  ValueError Traceback (most recent call last)
  ...
  ----> 1 (foo < 40) or (foo > 60)
  ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

有没有一种标准的方法,可以让我们在NumPy数组上进行逐元素的布尔操作,同时代码看起来更好看呢?

4 个回答

26

如果你只是在比较布尔值,比如你举的例子,那可以使用位或运算符 |,就像Jcollado建议的那样。不过要小心,如果你用非布尔值,结果可能会很奇怪,比如 mask = (foo < 40) | override。只有当 override 确保是 False、True、1 或 0 时,这样用才没问题。

更通用的方法是使用NumPy的比较集合运算符 np.anynp.all。这个代码片段会返回所有在35到45之间的值,这些值要么小于40,要么不是3的倍数:

import numpy as np
foo = np.arange(35, 46)
mask = np.any([(foo < 40), (foo % 3)], axis=0)
print foo[mask]
OUTPUT: array([35, 36, 37, 38, 39, 40, 41, 43, 44])

虽然用 | 的方式不如这样好看,但比你问题里的代码要好一些。

30

你可以使用NumPy的逻辑运算。在你的例子中:

np.logical_or(foo < 40, foo > 60)
120

试试这个:

mask = (foo < 40) | (foo > 60)

注意:对象中的 __or__ 方法是重载位运算符 |,而不是布尔运算符 or

撰写回答