web-dev-qa-db-fra.com

Tableau Numpy, comment sélectionner des index répondant à plusieurs conditions?

Supposons que j'ai un tableau numpy x = [5, 2, 3, 1, 4, 5], y = ['f', 'o', 'o', 'b', 'a', 'r']. Je souhaite sélectionner les éléments dans y correspondant aux éléments de x qui sont supérieurs à 1 et inférieurs à 5.

J'ai essayé

x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']

mais ça ne marche pas. Comment je ferais ça?

105
Bob

Votre expression fonctionne si vous ajoutez des parenthèses:

>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'], 
      dtype='|S1')
171
jfs

IMO OP ne veut pas réellement np.bitwise_and() (alias &) mais veut réellement np.logical_and() car ils comparent des valeurs logiques telles que True et False - voir ce SO post sur logique vs bit pour voir la différence.

>>> x = array([5, 2, 3, 1, 4, 5])
>>> y = array(['f','o','o','b','a','r'])
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

Et la manière équivalente de le faire est avec np.all() en définissant correctement l’argument axis.

>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

en chiffres:

>>> %timeit (a < b) & (b < c)
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 1.15 µs per loop

>>> %timeit np.logical_and(a < b, b < c)
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.17 µs per loop

>>> %timeit np.all([a < b, b < c], 0)
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.06 µs per loop

si utiliser np.all() est plus lent, mais & et logical_and sont à peu près les mêmes.

29
Mark Mikofski

Ajouter un détail à @ J.F. Réponses de Sebastian et @Mark Mikofski:
Si on veut obtenir les index correspondants (plutôt que les valeurs réelles du tableau), le code suivant fera:

Pour satisfaire plusieurs (toutes) conditions:

select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] #   1 < x <5

Pour satisfaire plusieurs (ou) conditions:

select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5
17
Good Will

J'aime utiliser np.vectorize pour de telles tâches. Considérer ce qui suit:

>>> # Arrays
>>> x = np.array([5, 2, 3, 1, 4, 5])
>>> y = np.array(['f','o','o','b','a','r'])

>>> # Function containing the constraints
>>> func = np.vectorize(lambda t: t>1 and t<5)

>>> # Call function on x
>>> y[func(x)]
>>> array(['o', 'o', 'a'], dtype='<U1')

L'avantage est que vous pouvez ajouter beaucoup plus de types de contraintes dans la fonction vectorisée.

J'espère que ça aide.

5
user4340135

En fait, je le ferais de cette façon:

L1 est la liste d'index des éléments satisfaisant la condition 1. Vous pouvez peut-être utiliser somelist.index(condition1) ou np.where(condition1) pour obtenir L1.

De même, vous obtenez L2, une liste d'éléments satisfaisant la condition 2;

Ensuite, vous trouvez l'intersection à l'aide de intersect(L1,L2).

Vous pouvez également trouver l'intersection de plusieurs listes si vous devez satisfaire à plusieurs conditions.

Ensuite, vous pouvez appliquer un index à n’importe quel autre tableau, par exemple x.

1
Shuo Yang

Pour les tableaux 2D, vous pouvez le faire. Créez un masque 2D en utilisant la condition. Convertissez le masque de condition en int ou en float, selon le tableau, et multipliez-le par le tableau d'origine.

In [8]: arr
Out[8]: 
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])

In [9]: arr*(arr % 2 == 0).astype(np.int) 
Out[9]: 
array([[ 0.,  2.,  0.,  4.,  0.],
       [ 6.,  0.,  8.,  0., 10.]])
0
Gautam