J'ai deux points en 3D:
(xa, ya, za)
(xb, yb, zb)
Et je veux calculer la distance:
dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
Quelle est la meilleure façon de le faire avec NumPy, ou avec Python en général? J'ai:
import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))
python
numpy
euclidean-distance
Nathan Fellman
la source
la source
Il y a une fonction pour cela dans SciPy. Cela s'appelle euclidien .
Exemple:
la source
Pour tous ceux qui souhaitent calculer plusieurs distances à la fois, j'ai fait une petite comparaison en utilisant perfplot (un petit projet à moi).
Le premier conseil est d'organiser vos données de manière à ce que les tableaux aient une dimension
(3, n)
(et soient évidemment contigus en C). Si l'ajout se produit dans la première dimension contiguë, les choses sont plus rapides et peu importe si vous utilisezsqrt-sum
avecaxis=0
,linalg.norm
avecaxis=0
ouqui est, par une légère marge, la variante la plus rapide. (Cela vaut également pour une seule ligne.)
Les variantes où vous résumez le deuxième axe
axis=1
, sont toutes beaucoup plus lentes.Code pour reproduire l'intrigue:
la source
i,i->
data
ressembler?Je veux exposer la réponse simple avec diverses notes de performance. np.linalg.norm fera peut-être plus que ce dont vous avez besoin:
Premièrement - cette fonction est conçue pour travailler sur une liste et renvoyer toutes les valeurs, par exemple pour comparer la distance de
pA
à l'ensemble de pointssP
:Rappelez-vous plusieurs choses:
Donc
n'est pas aussi innocent qu'il n'y paraît.
Premièrement - chaque fois que nous l'appelons, nous devons faire une recherche globale pour "np", une recherche de portée pour "linalg" et une recherche de portée pour "norm", et la surcharge de simplement appeler la fonction peut correspondre à des dizaines de python instructions.
Enfin, nous avons gaspillé deux opérations pour stocker le résultat et le recharger pour le retour ...
Première passe à l'amélioration: accélérer la recherche, sauter le magasin
Nous obtenons le beaucoup plus rationalisé:
Cependant, la surcharge de l'appel de fonction représente encore un peu de travail. Et vous voudrez faire des repères pour déterminer si vous feriez mieux de faire les calculs vous-même:
Sur certaines plateformes,
**0.5
est plus rapide quemath.sqrt
. Votre kilométrage peut varier.**** Notes de performance avancées.
Pourquoi calculez-vous la distance? Si le seul but est de l'afficher,
avancer. Mais si vous comparez des distances, effectuez des vérifications de portée, etc., j'aimerais ajouter quelques observations utiles sur les performances.
Prenons deux cas: tri par distance ou élimination d'une liste des éléments qui répondent à une contrainte de plage.
La première chose dont nous devons nous souvenir est que nous utilisons Pythagore pour calculer la distance (
dist = sqrt(x^2 + y^2 + z^2)
), donc nous faisons beaucoup d'sqrt
appels. Math 101:En bref: jusqu'à ce que nous ayons réellement besoin de la distance dans une unité de X plutôt que X ^ 2, nous pouvons éliminer la partie la plus difficile des calculs.
Génial, les deux fonctions ne font plus de racines carrées coûteuses. Ce sera beaucoup plus rapide. Nous pouvons également améliorer in_range en le convertissant en générateur:
Cela a surtout des avantages si vous faites quelque chose comme:
Mais si la prochaine chose que vous allez faire nécessite une distance,
pensez à donner des tuples:
Cela peut être particulièrement utile si vous pouvez enchaîner des vérifications de plage (`` trouver des choses qui sont proches de X et à Nm de Y '', car vous n'avez pas à calculer à nouveau la distance).
Mais qu'en est-il si nous recherchons une très grande liste
things
et que nous prévoyons que beaucoup d'entre eux ne méritent pas d'être pris en considération?Il y a en fait une optimisation très simple:
Son utilité dépendra de la taille des «choses».
Et encore une fois, envisagez de fournir le dist_sq. Notre exemple de hot-dog devient alors:
la source
pointZ
qui n'existait pas. Je pense que vous vouliez dire deux points dans un espace tridimensionnel et j'ai édité en conséquence. Si je me trompais, faites-le moi savoir.Un autre exemple de cette méthode de résolution de problèmes :
la source
norm = lambda x: N.sqrt(N.square(x).sum())
;norm(x-y)
numpy.linalg.norm(x-y)
En commençant
Python 3.8
, lemath
module fournit directement ladist
fonction, qui retourne la distance euclidienne entre deux points (donnée sous forme de tuples ou de listes de coordonnées):Et si vous travaillez avec des listes:
la source
Cela peut être fait comme suit. Je ne sais pas à quelle vitesse c'est, mais il n'utilise pas NumPy.
la source
for a, b in zip(a, b)
. Mais utile néanmoins.Je trouve une fonction 'dist' dans matplotlib.mlab, mais je ne pense pas que ce soit assez pratique.
Je le poste ici juste pour référence.
la source
J'aime
np.dot
(produit scalaire):la source
Une belle doublure:
Cependant, si la vitesse est un problème, je recommanderais d'expérimenter sur votre machine. J'ai trouvé que l'utilisation de la
math
bibliothèquesqrt
avec l'**
opérateur pour le carré est beaucoup plus rapide sur ma machine que la solution NumPy à une ligne.J'ai exécuté mes tests en utilisant ce programme simple:
Sur ma machine,
math_calc_dist
tourne beaucoup plus vite quenumpy_calc_dist
: 1,5 seconde contre 23,5 secondes.Pour obtenir une différence mesurable entre
fastest_calc_dist
etmath_calc_dist
j'ai dû jusqu'àTOTAL_LOCATIONS
6000. Prend ensuitefastest_calc_dist
~ 50 secondes tandis quemath_calc_dist
prend ~ 60 secondes.Vous pouvez également expérimenter avec
numpy.sqrt
etnumpy.square
bien que les deux soient plus lents que lesmath
alternatives sur ma machine.Mes tests ont été exécutés avec Python 2.6.6.
la source
scipy.spatial.distance.cdist(p1, p2).sum()
. C'est ça.numpy.linalg.norm(p1-p2).sum()
pour obtenir la somme entre chaque point de p1 et le point correspondant de p2 (c'est-à-dire pas tous les points de p1 à tous les points de p2). Et si vous voulez chaque point de p1 à chaque point de p2 et que vous ne voulez pas utiliser scipy comme dans mon commentaire précédent, vous pouvez utiliser np.apply_along_axis avec numpy.linalg.norm pour le faire encore beaucoup, beaucoup plus rapidement alors votre solution "la plus rapide".Vous pouvez simplement soustraire les vecteurs puis le produit interne.
En suivant votre exemple,
la source
Ayant
a
etb
comme vous les avez définis, vous pouvez également utiliser:la source
Avec Python 3.8, c'est très simple.
https://docs.python.org/3/library/math.html#math.dist
la source
Voici un code concis pour la distance euclidienne en Python étant donné deux points représentés sous forme de listes en Python.
la source
Depuis Python 3.8
Depuis Python 3.8, le
math
module inclut la fonctionmath.dist()
.Voir ici https://docs.python.org/3.8/library/math.html#math.dist .
la source
Calculez la distance euclidienne pour l'espace multidimensionnel:
la source
la source
la source
Vous pouvez facilement utiliser la formule
ce qui ne fait en fait rien de plus que d'utiliser le théorème de Pythagore pour calculer la distance, en ajoutant les carrés de Δx, Δy et Δz et enracinant le résultat.
la source
Trouvez d'abord la différence de deux matrices. Ensuite, appliquez la multiplication par élément avec la commande multiply de numpy. Après cela, trouvez la somme de la nouvelle matrice multipliée par élément. Enfin, trouvez la racine carrée de la sommation.
la source
Vous devez d' abord la liste des modifications à tableau numpy et faire comme ceci:
print(np.linalg.norm(np.array(a) - np.array(b)))
. Deuxième méthode directement à partir de la liste python:print(np.linalg.norm(np.subtract(a,b)))
la source