Как выполнять элементарные булевы операции над массивами numpy
Например, я хотел бы создать маску, которая маскирует элементы со значением от 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 ответов:
Вы пробовали это?
mask = (foo < 40) | (foo > 60)Примечание: метод
__or__в объекте перегружает побитовый оператор or (|), а не булев операторor.
Если у вас есть сравнения только внутри булевых символов, как в вашем примере, вы можете использовать побитовый оператор OR
|, как предлагает Jcollado. Но будьте осторожны, это может дать вам странные результаты, если вы когда-либо используете не булевы, такие какmask = (foo < 40) | override. Только до тех пор, покаoverrideгарантированно будет ложным, истинным, 1 или 0, вы в порядке.Более общим является использование операторов множества сравнения numpy,
np.anyиnp.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])Не так хорошо, как с
|, но лучше, чем код в вашем вопросе.
Можно использовать логические операции numpy. В вашем примере:
np.logical_or(foo < 40, foo > 60)
Обратите внимание, что вы можете использовать
~для элементного отрицания.arr = np.array([False, True]) ~arr OUTPUT: array([ True, False], dtype=bool)Также
&делает элементарно иarr_1 = np.array([False, False, True, True]) arr_2 = np.array([False, True, False, True]) arr_1 & arr_2 OUTPUT: array([False, False, False, True], dtype=bool)Они также работают спандами серии
ser_1 = pd.Series([False, False, True, True]) ser_2 = pd.Series([False, True, False, True]) ser_1 & ser_2 OUTPUT: 0 False 1 False 2 False 3 True dtype: bool
Comments