6
votes

Comment faire correspondre des paires de valeurs contenues dans deux tableaux numpy

J'ai deux ensembles de coordonnées et je veux savoir quelles coordonnées de l'ensemble coo sont identiques à n'importe quelle coordonnée dans l'ensemble cibles . Je veux connaître les indices dans l'ensemble coo , ce qui signifie que je voudrais obtenir une liste d'indices ou de booléens.

[False True True False] # bool list
[1,2] # list of concerning indices

Le résultat souhaité serait un des deux suivants:

import numpy as np

coo = np.array([[1,2],[1,6],[5,3],[3,6]]) # coordinates
targets = np.array([[5,3],[1,6]]) # coordinates of targets

print(np.isin(coo,targets))

[[ True False]
 [ True  True]
 [ True  True]
 [ True  True]]

Mon problème est que ...

  • np.isin n'a pas d'attribut axis pour que je puisse utiliser axis = 1 .
  • même appliquer et à chaque ligne de la sortie renverrait True pour le dernier élément, ce qui est faux.

Je connais les boucles et les conditions, mais je suis sûr que Python est équipé de moyens pour une solution plus élégante.


0 commentaires

3 Réponses :


13
votes

Cette solution sera moins adaptée pour les grands tableaux , dans ce cas, les autres réponses proposées fonctionneront mieux.


Voici une façon de tirer parti de diffusion :

(coo[:,None] == targets).all(2)

array([[False, False],
       [False,  True],
       [ True, False],
       [False, False]])


0 commentaires

1
votes

Voici une solution simple et intuitive qui utilise en fait numpy.isin () , pour faire correspondre les tuples , plutôt que des numéros individuels:

[False  True  True False]
[1 2]


0 commentaires

2
votes

Le package numpy_indexed met en œuvre la fonctionnalité de ce tapez de manière vectorisée (avertissement: je suis son auteur). Malheureusement, numpy manque beaucoup de cette fonctionnalité hors de la boîte; J'ai commencé numpy_indexed avec l'intention de le fusionner dans numpy, mais il y a des problèmes de compatibilité descendante, et les gros paquets comme celui-ci ont tendance à se déplacer lentement. Cela ne s'est donc pas produit au cours des 3 dernières années; mais l'écosystème d'empaquetage python fonctionne si bien de nos jours que l'ajout d'un paquet supplémentaire à votre environnement est tout aussi simple, vraiment.

import numpy_indexed as npi
bools = npi.in_(targets, coo)

Cela aura une complexité temporelle similaire à celle de la solution publiée par @fountainhead (logarithmique plutôt que linéaire, selon la réponse actuellement acceptée), mais aussi la bibliothèque npi vous donnera la sécurité des tests automatisés, et de nombreuses autres options pratiques, si vous décidez d'aborder le problème d'une manière légèrement différente angle.


3 commentaires

Je ne suis pas sûr que la réponse actuellement acceptée ait une complexité temporelle linéaire. Lorsque nous commençons avec deux tableaux de nombres de taille 2m et de nombres 2n respectivement, la taille diffusée sera de 2mn . Ainsi, la comparaison == des tableaux diffusés effectuera toujours une comparaison numérique de 2mn . Ce sera toujours 2mn des comparaisons, et pas seulement dans le pire des cas . (Le pire des cas est lorsqu'il n'y a aucune correspondance). En revanche, les solutions basées sur isin arrêtent les correspondances supplémentaires lorsque chaque correspondance réussie se produit.


C'est linéaire à la fois en n et en m; tellement quadratique si vous mettez les deux à l'échelle en même temps. C'est en effet aussi brutal que possible, et des solutions plus intelligentes peuvent avoir un énorme avantage dans la pratique


ne devrait-il pas être l'inverse? npi.in_ (coo, cibles)? J'ai essayé votre classe et cela n'a fonctionné que de cette façon et la documentation le dit également. À votre santé.