web-dev-qa-db-fra.com

Numpy où fonction plusieurs conditions

J'ai un tableau de distances appelé dists. Je veux sélectionner des dists qui sont entre deux valeurs. J'ai écrit la ligne de code suivante pour le faire:

 dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))]

Cependant cela ne sélectionne que pour la condition 

 (np.where(dists <= r + dr))

Si je fais les commandes séquentiellement en utilisant une variable temporaire, cela fonctionne très bien. Pourquoi le code ci-dessus ne fonctionne-t-il pas et comment puis-je le faire fonctionner? 

À votre santé

85
user1654183

La meilleure façon de votre cas particulier serait simplement de changer vos deux critères en un critère:

dists[abs(dists - r - dr/2.) <= dr/2.]

Il crée seulement un tableau booléen, et à mon avis, il est plus facile à lire car il dit, est dist dans un dr ou r? (Bien que je redéfinisse r pour être le centre de votre région d’intérêt au lieu du début, donc r = r + dr/2.) Mais cela ne répond pas à votre question.


La réponse à votre question:
Vous n'avez pas réellement besoin de where si vous essayez simplement de filtrer les éléments de dists qui ne correspondent pas à vos critères:

dists[(dists >= r) & (dists <= r+dr)]

Parce que le & vous donnera un élément and (les parenthèses sont nécessaires).

Ou, si vous voulez utiliser where pour une raison quelconque, vous pouvez faire:

 dists[(np.where((dists >= r) & (dists <= r + dr)))]

Pourquoi:
La raison pour laquelle cela ne fonctionne pas, c'est parce que np.where renvoie une liste d'index, pas un tableau booléen. Vous essayez d’obtenir and entre deux listes de nombres, qui n’ont bien sûr pas les valeurs True/False que vous attendez. Si a et b sont tous deux True valeurs, alors a and b renvoie b. Ainsi, dire quelque chose comme [0,1,2] and [2,3,4] vous donnera simplement [2,3,4]. Ici c'est en action:

In [230]: dists = np.arange(0,10,.5)
In [231]: r = 5
In [232]: dr = 1

In [233]: np.where(dists >= r)
Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),)

In [234]: np.where(dists <= r+dr)
Out[234]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

In [235]: np.where(dists >= r) and np.where(dists <= r+dr)
Out[235]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

Ce que vous vous attendiez à comparer était simplement le tableau booléen, par exemple

In [236]: dists >= r
Out[236]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True], dtype=bool)

In [237]: dists <= r + dr
Out[237]: 
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

In [238]: (dists >= r) & (dists <= r + dr)
Out[238]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

Vous pouvez maintenant appeler np.where sur le tableau booléen combiné:

In [239]: np.where((dists >= r) & (dists <= r + dr))
Out[239]: (array([10, 11, 12]),)

In [240]: dists[np.where((dists >= r) & (dists <= r + dr))]
Out[240]: array([ 5. ,  5.5,  6. ])

Ou simplement indexez le tableau d'origine avec le tableau booléen en utilisant indexation de fantaisie

In [241]: dists[(dists >= r) & (dists <= r + dr)]
Out[241]: array([ 5. ,  5.5,  6. ])
165
askewchan

Depuis la réponse acceptée a très bien expliqué le problème. vous pouvez également utiliser fonctions logiques numpy qui convient mieux ici à plusieurs conditions:

np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr)))
34
Kasrâmvd

Essayer:

np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])
2
Xin Wang

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

>>> # function which returns True when constraints are satisfied.
>>> func = lambda d: d >= r and d<= (r+dr) 
>>>
>>> # Apply constraints element-wise to the dists array.
>>> result = np.vectorize(func)(dists) 
>>>
>>> result = np.where(result) # Get output.

Vous pouvez également utiliser np.argwhere au lieu de np.where pour effacer la sortie. Mais c'est votre appel :)

J'espère que ça aide.

2
user4340135

Essayer:

import numpy as np
dist = np.array([1,2,3,4,5])
r = 2
dr = 3
np.where(np.logical_and(dist> r, dist<=r+dr))

Sortie: (tableau ([2, 3]),)

Vous pouvez voir Fonctions logiques pour plus de détails.

1
Xiong-Hui Chen

J'ai élaboré cet exemple simple 

import numpy as np

ar = np.array([3,4,5,14,2,4,3,7])

print [X for X in list(ar) if (X >= 3 and X <= 6)]

>>> 
[3, 4, 5, 4, 3]
0
octoback

Cela devrait fonctionner:

dists[((dists >= r) & (dists <= r+dr))]

La manière la plus élégante ~~

0
Qhan