我在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))
答案 0 :(得分:707)
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))
最快地计算a
和b
行的距离。这实际上只适用于一行!
重现情节的代码:
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)
但是,如果速度是一个问题,我建议您在机器上进行试验。我发现在我的机器上使用math
库sqrt
和**
运算符的方块比单线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_dist
和math_calc_dist
之间获得可衡量的差异,我必须将TOTAL_LOCATIONS
提高到6000.然后fastest_calc_dist
需要 ~50秒 math_calc_dist
需要 ~60秒。
您也可以试用numpy.sqrt
和numpy.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)
如您所定义a
和b
,您还可以使用:
distance = np.sqrt(np.sum((a-b)**2))
答案 11 :(得分:3)
这里有一些关于Python中欧几里德距离的简明代码,给出了两个用Python表示的列表。
Has instance field 'mainLocation' of type String
答案 12 :(得分:3)
从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-y
由255
组成,这表示两个图像彼此相距很远。对于无符号整数类型(例如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)