在三维空间中有两个点
a = (ax, ay, az)
b = (bx, by, bz)
我想计算它们之间的距离:
dist = sqrt((ax-bx)^2 + (ay-by)^2 + (az-bz)^2)
我如何用NumPy做到这一点?我有:
import numpy
a = numpy.array((ax, ay, az))
b = numpy.array((bx, by, bz))
在三维空间中有两个点
a = (ax, ay, az)
b = (bx, by, bz)
我想计算它们之间的距离:
dist = sqrt((ax-bx)^2 + (ay-by)^2 + (az-bz)^2)
我如何用NumPy做到这一点?我有:
import numpy
a = numpy.array((ax, ay, az))
b = numpy.array((bx, by, bz))
当前回答
从Python 3.8开始
从Python 3.8开始,数学模块包含了math.dist()函数。 请看这里https://docs.python.org/3.8/library/math.html#math.dist。
数学。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
其他回答
这种解决问题方法的另一个例子:
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)
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)
从Python 3.8开始,math模块直接提供dist函数,它返回两点之间的欧几里得距离(以元组或坐标列表的形式给出):
from math import dist
dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845
如果你使用列表:
dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845
你可以减去向量,然后内积。
以你为榜样,
a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))
tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result = numpy.sqrt(sum_squared)
对于那些对一次计算多个距离感兴趣的人来说,我已经使用perfplot(我的一个小项目)做了一些比较。
第一个建议是组织数据,使数组具有维数(3,n)(显然是c连续的)。如果加法发生在连续的第一维中,事情会更快,如果你使用带有axis=0的sqrt-sum, linalg,它也不会太重要。轴=0的范数,或
a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))
这是,以微弱优势,最快的变种。(这实际上也只适用于一行。)
在第二个轴上求和的变量,轴=1,都要慢得多。
代码重现情节:
import numpy
import perfplot
from scipy.spatial import distance
def linalg_norm(data):
a, b = data[0]
return numpy.linalg.norm(a - b, axis=1)
def linalg_norm_T(data):
a, b = data[1]
return numpy.linalg.norm(a - b, axis=0)
def sqrt_sum(data):
a, b = data[0]
return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))
def sqrt_sum_T(data):
a, b = data[1]
return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))
def scipy_distance(data):
a, b = data[0]
return list(map(distance.euclidean, a, b))
def sqrt_einsum(data):
a, b = data[0]
a_min_b = a - b
return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))
def sqrt_einsum_T(data):
a, b = data[1]
a_min_b = a - b
return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))
def setup(n):
a = numpy.random.rand(n, 3)
b = numpy.random.rand(n, 3)
out0 = numpy.array([a, b])
out1 = numpy.array([a.T, b.T])
return out0, out1
b = perfplot.bench(
setup=setup,
n_range=[2 ** k for k in range(22)],
kernels=[
linalg_norm,
linalg_norm_T,
scipy_distance,
sqrt_sum,
sqrt_sum_T,
sqrt_einsum,
sqrt_einsum_T,
],
xlabel="len(x), len(y)",
)
b.save("norm.png")