如何用NumPy计算欧氏距离?

时间:2009-09-09 19:48:49

标签: python numpy euclidean-distance

我在3D中有两点:

(xa, ya, za)
(xb, yb, zb)

我想计算距离:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

使用NumPy或Python的最佳方法是什么?我有:

a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

21 个答案:

答案 0 :(得分:707)

使用numpy.linalg.norm

dist = numpy.linalg.norm(a-b)

答案 1 :(得分:123)

SciPy中有一个功能。它被称为Euclidean

示例:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

答案 2 :(得分:76)

对于有兴趣一次计算多个距离的人,我使用perfplot(我的一个小项目)进行了一些比较。事实证明

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->i', a_min_b, a_min_b))

最快地计算ab行的距离。这实际上只适用于一行!

enter image description here

重现情节的代码:

import matplotlib
import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data
    return numpy.linalg.norm(a-b, axis=1)


def sqrt_sum(data):
    a, b = data
    return numpy.sqrt(numpy.sum((a-b)**2, axis=1))


def scipy_distance(data):
    a, b = data
    return list(map(distance.euclidean, a, b))


def mpl_dist(data):
    a, b = data
    return list(map(matplotlib.mlab.dist, a, b))


def sqrt_einsum(data):
    a, b = data
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum('ij,ij->i', a_min_b, a_min_b))


perfplot.show(
    setup=lambda n: numpy.random.rand(2, n, 3),
    n_range=[2**k for k in range(20)],
    kernels=[linalg_norm, scipy_distance, mpl_dist, sqrt_sum, sqrt_einsum],
    logx=True,
    logy=True,
    xlabel='len(x), len(y)'
    )

答案 3 :(得分:33)

this problem solving method的另一个例子:

def dist(x,y):   
    return numpy.sqrt(numpy.sum((x-y)**2))

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))
dist_a_b = dist(a,b)

答案 4 :(得分:10)

我找到了一个' dist' dist功能在matplotlib.mlab中,但我认为它不够方便。

我在这里发帖仅供参考。

import numpy as np
import matplotlib as plt

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

# Distance between a and b
dis = plt.mlab.dist(a, b)

答案 5 :(得分:9)

可以像下面那样完成。我不知道它有多快,但它没有使用NumPy。

from math import sqrt
a = (1, 2, 3) # Data point 1
b = (4, 5, 6) # Data point 2
print sqrt(sum( (a - b)**2 for a, b in zip(a, b)))

答案 6 :(得分:6)

我喜欢IsSelected(点积):

show.html.erb

答案 7 :(得分:6)

Python 3.8开始,math模块直接提供dist函数,该函数返回两点之间的欧几里得距离(以坐标元组给出):

from python import math

dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845

如果要使用列表而不是元组:

dist(tuple([1, 2, 6]), tuple([-2, 3, 2]))

答案 8 :(得分:5)

一个不错的单行:

dist = numpy.linalg.norm(a-b)

但是,如果速度是一个问题,我建议您在机器上进行试验。我发现在我的机器上使用mathsqrt**运算符的方块比单线NumPy解决方案快得多。

我使用这个简单的程序运行我的测试:

#!/usr/bin/python
import math
import numpy
from random import uniform

def fastest_calc_dist(p1,p2):
    return math.sqrt((p2[0] - p1[0]) ** 2 +
                     (p2[1] - p1[1]) ** 2 +
                     (p2[2] - p1[2]) ** 2)

def math_calc_dist(p1,p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
                     math.pow((p2[1] - p1[1]), 2) +
                     math.pow((p2[2] - p1[2]), 2))

def numpy_calc_dist(p1,p2):
    return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))

TOTAL_LOCATIONS = 1000

p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
    p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
    p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))

total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
    for j in range(0, TOTAL_LOCATIONS):
        dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
        total_dist += dist

print total_dist

在我的计算机上,math_calc_dist的运行速度远远超过numpy_calc_dist 1.5秒,而 23.5秒

要在fastest_calc_distmath_calc_dist之间获得可衡量的差异,我必须将TOTAL_LOCATIONS提高到6000.然后fastest_calc_dist需要 ~50秒 math_calc_dist需要 ~60秒

您也可以试用numpy.sqrtnumpy.square,但两者都比我机器上的math替代品慢。

我的测试是使用Python 2.6.6运行的。

答案 9 :(得分:5)

你可以减去向量然后减去内积。

按照你的例子,

a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))

tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result sqrt(sum_squared)

代码简单,易于理解。

答案 10 :(得分:5)

如您所定义ab,您还可以使用:

distance = np.sqrt(np.sum((a-b)**2))

答案 11 :(得分:3)

这里有一些关于Python中欧几里德距离的简明代码,给出了两个用Python表示的列表。

Has instance field 'mainLocation' of type String

答案 12 :(得分:3)

自Python 3.8起

从Python 3.8开始,math模块包含函数math.dist()
参见此处https://docs.python.org/3.8/library/math.html#math.dist

  

math.dist(p1,p2)
  返回两个点p1和p2之间的欧几里得距离,   每个给定为坐标序列(或可迭代)。

import math
print( math.dist( (0,0),   (1,1)   )) # sqrt(2) -> 1.4142
print( math.dist( (0,0,0), (1,1,1) )) # sqrt(3) -> 1.7321

答案 13 :(得分:1)

计算多维空间的欧几里德距离:

 import math

 x = [1, 2, 6] 
 y = [-2, 3, 2]

 dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
 5.0990195135927845

答案 14 :(得分:1)

import numpy as np
# any two python array as two points
a = [0, 0]
b = [3, 4]

您首先将列表更改为 numpy数组,然后执行以下操作:print(np.linalg.norm(np.array(a) - np.array(b)))。直接从python列表中获取的第二种方法为:print(np.linalg.norm(np.subtract(a,b)))

答案 15 :(得分:1)

使用Python 3.8,非常简单。

https://docs.python.org/3/library/math.html#math.dist

math.dist(p, q)
  

返回两个点p和q之间的欧几里得距离,分别给定   作为坐标序列(或可迭代)。两点必须有   尺寸相同。

     

大致等同于:

     

sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))

答案 16 :(得分:1)

您可以轻松使用公式

distance = np.sqrt(np.sum(np.square(a-b)))

实际上只是使用毕达哥拉斯定理计算距离,通过加上Δx,Δy和Δz的平方并将结果生根。

答案 17 :(得分:1)

import math

dist = math.hypot(math.hypot(xa-xb, ya-yb), za-zb)

答案 18 :(得分:1)

import numpy as np
from scipy.spatial import distance
input_arr = np.array([[0,3,0],[2,0,0],[0,1,3],[0,1,2],[-1,0,1],[1,1,1]]) 
test_case = np.array([0,0,0])
dst=[]
for i in range(0,6):
    temp = distance.euclidean(test_case,input_arr[i])
    dst.append(temp)
print(dst)

答案 19 :(得分:0)

首先找到两个矩阵的差。然后,通过numpy的乘法命令应用逐元素乘法。然后,找到逐元素相乘的新矩阵的总和。最后,找到求和的平方根。

def findEuclideanDistance(a, b):
    euclidean_distance = a - b
    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
    euclidean_distance = np.sqrt(euclidean_distance)
    return euclidean_distance

答案 20 :(得分:0)

其他答案适用于浮点数,但不能正确计算整数dtype的距离,整数dtypes会发生上溢和下溢。请注意,甚至scipy.distance.euclidean都存在以下问题:

>>> a1 = np.array([1], dtype='uint8')
>>> a2 = np.array([2], dtype='uint8')
>>> a1 - a2
array([255], dtype=uint8)
>>> np.linalg.norm(a1 - a2)
255.0
>>> from scipy.spatial import distance
>>> distance.euclidean(a1, a2)
255.0

这是常见的,因为许多图像库使用dtype =“ uint8”将图像表示为ndarray。这意味着,如果您有一个由非常深的灰色像素组成的灰度图像(例如,所有像素的颜色均为#000001),并且将其与黑色图像(#000000)进行了对比,那么最终其中所有单元格中的x-y255组成,这表示两个图像彼此相距很远。对于无符号整数类型(例如uint8),您可以安全地以numpy计算距离:

np.linalg.norm(np.maximum(x, y) - np.minimum(x, y))

对于有符号整数类型,可以先将其强制转换为浮点数:

np.linalg.norm(x.astype("float") - y.astype("float"))

对于图像数据,可以使用opencv的norm方法:

import cv2
cv2.norm(x, y, cv2.NORM_L2)