tester si un tableau Numpy contient une ligne donnée
Est-il un Pythonic et efficace pour vérifier si un tableau Numpy contient au moins une instance d'une ligne donnée? Par "efficace", je veux dire il se termine sur la découverte de la première ligne plutôt que de parcourir l'ensemble du tableau, même si un résultat a déjà été trouvé.
Avec Python tableaux ceci peut être accompli très proprement avec if row in array:
, mais cela ne fonctionne pas comme je voudrais attendre pour les tableaux Numpy, comme illustré ci-dessous.
Avec Python tableaux:
>>> a = [[1,2],[10,20],[100,200]]
>>> [1,2] in a
True
>>> [1,20] in a
False
mais Numpy tableaux différents et plutôt bizarre résultats de recherche. (Le __contains__
méthode de ndarray
semble être sans-papiers.)
>>> a = np.array([[1,2],[10,20],[100,200]])
>>> np.array([1,2]) in a
True
>>> np.array([1,20]) in a
True
>>> np.array([1,42]) in a
True
>>> np.array([42,1]) in a
False
Vous êtes désireux de l'impossible. Numpy n'est actuellement pas fournir tout ce qui va arrêter lors de la constatation de la première. Cependant, si vous faites cela plusieurs fois de tri des approches beaucoup plus efficace de toute façon. Comme pour le comportement de
êtes-vous sûr qu'aucune solution n'existe? Si oui, alors c'est la réponse à ma question, donc s'il vous plaît poster et si je suis convaincu que je vais l'accepter. Aussi, si vous pourriez nous expliquer ce que vous entendez par "trier les approches fondées sur les" il serait utile. Mon tableau est en fait triés afin que le plus souvent recherchés-pour les lignes ont tendance à être vers le haut, si c'est ce que tu veux dire - mais ce n'est pas utiliser, à moins que la méthode de requête s'arrête une fois qu'il trouve une correspondance.
si
__contains__
je dirais presque qu'il s'agit d'un bug (c'est à dire qu'il fonctionne très bien pour les scalaires, mais les tableaux sont un peu bizarre, mais intérieurement il est juste tom10 dit de toute façon)êtes-vous sûr qu'aucune solution n'existe? Si oui, alors c'est la réponse à ma question, donc s'il vous plaît poster et si je suis convaincu que je vais l'accepter. Aussi, si vous pourriez nous expliquer ce que vous entendez par "trier les approches fondées sur les" il serait utile. Mon tableau est en fait triés afin que le plus souvent recherchés-pour les lignes ont tendance à être vers le haut, si c'est ce que tu veux dire - mais ce n'est pas utiliser, à moins que la méthode de requête s'arrête une fois qu'il trouve une correspondance.
si
__collect__
était en train de faire ce que tom10 dit la dernière entrée de la ligne cité dans ma question serait de retour True
, non?OriginalL'auteur Nathaniel | 2013-02-08
Vous devez vous connecter pour publier un commentaire.
Numpys
__contains__
est, au moment de la rédaction du présent,(a == b).tout()
qui est sans doute correcte uniquement sib
est un scalaire (c'est un peu poilu, mais je le crois, fonctionne comme ceci seulement en 1.7. ou plus tard – ce qui serait la bonne méthode générale(a == b).all(np.arange(a.ndim - b.ndim, a.ndim)).any()
, qui fait sens pour toutes les combinaisons dea
etb
dimensionnalité)...EDIT: Juste pour être clair, c'est pas nécessairement le résultat attendu lors de la diffusion est en cause. Quelqu'un pourrait argumenter qu'il doit traiter les articles dans
a
séparément commenp.in1d
n'. Je ne suis pas sûr qu'il y est une seule façon dont il devrait fonctionner.Maintenant, vous voulez numpy pour arrêter lorsqu'il trouve la première occurrence. Ce autant que je sache, il n'existe pas à cette époque. C'est difficile parce que numpy est basée principalement sur des ufuncs, qui font la même chose sur l'ensemble de la matrice.
Numpy n'est d'optimiser ce genre de réductions, mais efficace, qui fonctionne uniquement lorsque la matrice réduite est déjà un booléen tableau (c
np.ones(10, dtype=bool).any()
).Sinon il aurait besoin d'une fonction spéciale pour
__contains__
qui n'existe pas. Cela peut sembler étrange, mais vous devez vous rappeler que numpy prend en charge de nombreux types de données et a une plus grande machinerie de choisir celles qui sont correctes et sélectionnez la fonction correcte de travailler sur elle. Donc, en d'autres termes, la ufunc les machines ne peuvent pas le faire, et la mise en œuvre de__contains__
ou spéciale est en réalité pas si trivial parce que des types de données.Vous pouvez bien sûr écrire en python ou que vous le savez sans doute votre type de données, l'écriture elle-même en Cython/C est très simple.
Cela dit. Souvent, il est beaucoup mieux de toute façon à utiliser le tri en fonction de l'approche de ces choses. C'est un peu fastidieux, comme il n'y a pas une telle chose comme
searchsorted
pour unlexsort
, mais il fonctionne (vous pouvez aussi abuser descipy.spatial.cKDTree
si vous le souhaitez). Cela suppose que vous souhaitez comparer le long de la dernière axe seulement:Cela fonctionne aussi pour un tableau
b
, et si vous gardez le tableau trié, c'est aussi beaucoup mieux si vous le faites pour une seule valeur (ligne) dansb
à un moment, quanda
reste le même (sinon, je voudrais justenp.in1d
après la considérer comme une recarray). Important: vous devez faire lanp.ascontiguousarray
pour la sécurité. Il sera généralement rien, mais si c'est le cas, il serait d'un grand potentiel bug autrement.J'ai eu un IndexError quand
ind == len(sorted)
. Ce qui se passe sib
est "au-delà" de lasorted
tableau; par exemple,b = [101,0]
.OriginalL'auteur seberg
Vous pouvez utiliser .tolist()
Ou l'utilisation d'une vue:
Ou de générer plus de la numpy liste (potentiellement TRÈS LENT):
Ou utiliser numpy fonctions logiques:
Si vous avez le temps, ces:
Vous pouvez voir que frappé ou manquer, le numpy routines sont la même vitesse de recherche dans le tableau. Le Python
in
opérateur est potentiellement beaucoup plus rapidement pour un début de frapper, et le générateur est seulement de mauvaises nouvelles si vous devez aller tout le chemin à travers le tableau.Voici les résultats pour 300 000 x 3 élément de tableau:
Et pour les 3 000 000 x 3 tableau:
Ce qui semble indiquer que
np.equal
est le plus rapide pur numpy façon de le faire...tolist
n'. La première version de la question n'était pas claire à ce sujet; j'ai édité.La méthode de vue d'évaluer paresseusement? Je soupçonne que l'appel .tout sur la vue de créer un tout nouveau tableau, mais je ne sais pas comment trouver le hors.
Quelques points: 1) Dans la "vue", au lieu d'un[:], je pense que vous devriez utiliser un[...]; 2) dans la "logique", je pense que vous devriez utiliser np.tout et np.tous à la place de l'python; la 3), Il serait bon de faire une comparaison pour le résultat Faux, puisque ce sera très différent pour certains de ces cas (en particulier "gen"). +1, même si, pour une réelle efficacité de la mesure.
merci beaucoup pour la mise à jour. Je vois que dans mon cas d'utilisation de np.l'égalité sera probablement plus rapide que d'utiliser une liste Python, même si il n'a pas obtenir le bonus pour mettre fin à début. C'est très utile de le savoir.
Calendrier résultats sont les mieux accompli avec le
timeit
module: avec letime.time()
méthode, les résultats peuvent être très imprécis si le système exécute une autre tâche en arrière-plan (signalé temps est trop grand).OriginalL'auteur
Je pense que
liste les lignes qui correspondent. Comme Jamie points, pour savoir si au moins une telle ligne existe, utilisez
any
:De côté:
je soupçonne
in
(et__contains__
) est comme ci-dessus mais en utilisantany
au lieu deall
.np.any(...)
afin d'obtenir une adhésion valeur booléenne, si.Merci. Mais cela va itérer sur l'ensemble de la matrice et d'allouer un nouveau tableau dans la mémoire contenant l'ensemble des résultats, et ensuite seulement de vérifier pour voir si elle est vide. Une mise en œuvre efficace serait arrêter et retourner Vrai dès lors qu'il trouve la première ligne correspondante.
J'ai édité la question pour clarifier ce que je voulais dire par "efficace".
OriginalL'auteur tom10
Si vous voulez vraiment arrêter à la première occurrence, vous pourriez écrire une boucle, comme:
Cependant, je soupçonne fortement qu'il sera beaucoup plus lent que les autres suggestions concernant l'utilisation de numpy routines de le faire pour l'ensemble de la baie.
Honnêtement, si vous savez qu'il est généralement à la mendicité de la matrice, il n'est pas une mauvaise solution (et si
needle
est un assez grand tableau, c'est une bonne solution, en tout cas).OriginalL'auteur Bálint Aradi