Tengo dos puntos en 3D:
(xa, ya, za)
(xb, yb, zb)
Y quiero calcular la distancia:
dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
¿Cuál es la mejor manera de hacer esto con NumPy, o con Python en general? Yo tengo:
import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))
python
numpy
euclidean-distance
Nathan Fellman
fuente
fuente
Hay una función para eso en SciPy. Se llama euclidiana .
Ejemplo:
fuente
Para cualquier persona interesada en calcular múltiples distancias a la vez, he hecho una pequeña comparación usando perfplot (un pequeño proyecto mío).
El primer consejo es organizar sus datos de manera que las matrices tengan dimensión
(3, n)
(y obviamente sean contiguas en C). Si la adición ocurre en la primera dimensión contigua, las cosas son más rápidas y no importa demasiado si usasqrt-sum
conaxis=0
,linalg.norm
conaxis=0
oque es, por un ligero margen, la variante más rápida. (Eso también es cierto para solo una fila).
Las variantes en las que sumas sobre el segundo eje
axis=1
, son sustancialmente más lentas.Código para reproducir la trama:
fuente
i,i->
data
tiene que verse?Quiero exponer la respuesta simple con varias notas de rendimiento. np.linalg.norm hará quizás más de lo que necesita:
En primer lugar, esta función está diseñada para trabajar sobre una lista y devolver todos los valores, por ejemplo, para comparar la distancia desde
pA
el conjunto de puntossP
:Recuerda varias cosas:
Entonces
No es tan inocente como parece.
En primer lugar, cada vez que lo llamamos, tenemos que hacer una búsqueda global de "np", una búsqueda de alcance para "linalg" y una búsqueda de alcance para "norma", y la sobrecarga de simplemente llamar la función puede equivaler a docenas de python instrucciones.
Por último, desperdiciamos dos operaciones para almacenar el resultado y volver a cargarlo para devolverlo ...
Primer paso en la mejora: agilice la búsqueda, salte la tienda
Obtenemos el más simplificado:
Sin embargo, la sobrecarga de llamadas a funciones todavía equivale a algo de trabajo. Y querrás hacer puntos de referencia para determinar si podrías ser mejor haciendo los cálculos tú mismo:
En algunas plataformas,
**0.5
es más rápido quemath.sqrt
. Su experiencia puede ser diferente.**** Notas de rendimiento avanzadas.
¿Por qué estás calculando la distancia? Si el único propósito es mostrarlo,
superar. Pero si está comparando distancias, haciendo verificaciones de rango, etc., me gustaría agregar algunas observaciones útiles de rendimiento.
Tomemos dos casos: ordenar por distancia o seleccionar una lista de elementos que cumplan con una restricción de rango.
Lo primero que debemos recordar es que estamos usando Pitágoras para calcular la distancia (
dist = sqrt(x^2 + y^2 + z^2)
), por lo que estamos haciendo muchassqrt
llamadas. Matemáticas 101:En resumen: hasta que realmente necesitemos la distancia en una unidad de X en lugar de X ^ 2, podemos eliminar la parte más difícil de los cálculos.
Genial, ambas funciones ya no tienen raíces cuadradas caras. Eso será mucho más rápido. También podemos mejorar in_range convirtiéndolo en un generador:
Esto tiene beneficios especialmente si está haciendo algo como:
Pero si lo siguiente que vas a hacer requiere una distancia,
considere ceder tuplas:
Esto puede ser especialmente útil si puede encadenar verificaciones de rango ('encontrar cosas que están cerca de X y dentro de Nm de Y', ya que no tiene que calcular la distancia nuevamente).
Pero, ¿qué pasa si estamos buscando una lista realmente grande
things
y anticipamos que muchos de ellos no merecen ser considerados?En realidad, hay una optimización muy simple:
Si esto es útil dependerá del tamaño de las "cosas".
Y nuevamente, considere obtener el dist_sq. Nuestro ejemplo de hot dog se convierte en:
fuente
pointZ
que no existía. Creo que lo que querías decir era dos puntos en el espacio tridimensional y edité en consecuencia. Si me equivoqué, avíseme.Otra instancia de este método de resolución de problemas :
fuente
norm = lambda x: N.sqrt(N.square(x).sum())
;norm(x-y)
numpy.linalg.norm(x-y)
Comenzando
Python 3.8
, elmath
módulo proporciona directamente ladist
función, que devuelve la distancia euclidiana entre dos puntos (dados como tuplas o listas de coordenadas):Y si estás trabajando con listas:
fuente
Se puede hacer de la siguiente manera. No sé qué tan rápido es, pero no está usando NumPy.
fuente
for a, b in zip(a, b)
. Pero útil no obstante.Encuentro una función 'dist' en matplotlib.mlab, pero no creo que sea lo suficientemente útil.
Lo estoy publicando aquí solo como referencia.
fuente
Me gusta
np.dot
(producto de punto):fuente
Una buena frase:
Sin embargo, si la velocidad es una preocupación, recomendaría experimentar en su máquina. He encontrado que usar la
math
bibliotecasqrt
con**
operador para el cuadrado es mucho más rápido en mi máquina que la solución NumPy de una sola línea.Ejecuté mis pruebas usando este sencillo programa:
En mi máquina,
math_calc_dist
corre mucho más rápido quenumpy_calc_dist
: 1.5 segundos versus 23.5 segundos.Para obtener una diferencia medible entre
fastest_calc_dist
ymath_calc_dist
tuve que hastaTOTAL_LOCATIONS
6000. Luegofastest_calc_dist
toma ~ 50 segundos mientrasmath_calc_dist
toma ~ 60 segundos.También puede experimentar
numpy.sqrt
ynumpy.square
aunque ambos fueron más lentos que lasmath
alternativas en mi máquina.Mis pruebas se ejecutaron con Python 2.6.6.
fuente
scipy.spatial.distance.cdist(p1, p2).sum()
. Eso es.numpy.linalg.norm(p1-p2).sum()
para obtener la suma entre cada punto en p1 y el punto correspondiente en p2 (es decir, no todos los puntos en p1 a cada punto en p2). Y si desea cada punto en p1 a cada punto en p2 y no desea usar scipy como en mi comentario anterior, puede usar np.apply_along_axis junto con numpy.linalg.norm para hacerlo aún mucho, mucho más rápido entonces su solución "más rápida".Simplemente puede restar los vectores y luego el producto interno.
Siguiendo tu ejemplo,
fuente
Teniendo
a
yb
como los definiste, puedes usar también:fuente
Con Python 3.8, es muy fácil.
https://docs.python.org/3/library/math.html#math.dist
fuente
Aquí hay un código conciso para la distancia euclidiana en Python dados dos puntos representados como listas en Python.
fuente
Desde Python 3.8
Desde Python 3.8 el
math
módulo incluye la funciónmath.dist()
.Ver aquí https://docs.python.org/3.8/library/math.html#math.dist .
fuente
Calcule la distancia euclidiana para el espacio multidimensional:
fuente
fuente
fuente
Puedes usar fácilmente la fórmula
que en realidad no hace nada más que usar el teorema de Pitágoras para calcular la distancia, agregando los cuadrados de Δx, Δy y Δz y enraizando el resultado.
fuente
Encuentra la diferencia de dos matrices primero. Luego, aplique la multiplicación sabia de elementos con el comando de multiplicación de numpy. Después de eso, encuentre la suma de la nueva matriz multiplicada por elementos sabios. Finalmente, encuentre la raíz cuadrada de la sumatoria.
fuente
En primer lugar, la lista de cambios de serie numpy y hacerlo de esta manera:
print(np.linalg.norm(np.array(a) - np.array(b)))
. Segundo método directamente desde la lista de Python como:print(np.linalg.norm(np.subtract(a,b)))
fuente