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é
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. ])
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)))
Essayer:
np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])
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.
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.
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]
Cela devrait fonctionner:
dists[((dists >= r) & (dists <= r+dr))]
La manière la plus élégante ~~