web-dev-qa-db-fra.com

Comment effectuer des opérations booléennes par élément sur des tableaux numpy

Par exemple, je voudrais créer un masque qui masque les éléments dont la valeur est comprise entre 40 et 60:

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

Ce qui a l'air moche, je ne peux pas écrire:

(foo < 40) or (foo > 60)

parce que je me retrouve avec:

  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()

Existe-t-il une manière canonique de faire des opérations booléennes par élément sur des tableaux numpy avec un code beau?

46
jb.

Avez-vous essayé cela?

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

Noter la __or__ dans un objet surcharge l'opérateur au niveau du bit ou (|), pas l'opérateur booléen or.

70
jcollado

Si vous avez des comparaisons uniquement dans les booléens, comme dans votre exemple, vous pouvez utiliser l'opérateur au niveau du bit OR | Comme suggéré par Jcollado. Mais attention, cela peut vous donner des résultats étranges si vous utilisez des non-booléens, comme mask = (foo < 40) | override. Tant que override est garanti comme étant False, True, 1 ou 0, ça va.

Plus général est l'utilisation des opérateurs de jeu de comparaison de numpy, np.any Et np.all. Cet extrait renvoie toutes les valeurs comprises entre 35 et 45 qui sont inférieures à 40 ou non un multiple de 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])

Pas aussi bien qu'avec |, Mais plus agréable que le code de votre question.

15
dirkjot

Vous pouvez utiliser les opérations logiques numpy . Dans votre exemple:

np.logical_or(foo < 40, foo > 60)
9
ViennaMike

Notez que vous pouvez utiliser ~ pour la négation élément par élément.

arr = np.array([False, True])
~arr

OUTPUT: array([ True, False], dtype=bool)

Également & fait élément par élément et

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)

Ceux-ci fonctionnent également avec Pandas Series

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
3
Roko Mijic