在三维空间中有两个点

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))

当前回答

对于大量的距离,我能想到的最快的解决方案是使用numexpr。在我的机器上,它比使用numpy einsum更快:

import numexpr as ne
import numpy as np
np.sqrt(ne.evaluate("sum((a_min_b)**2,axis=1)"))

其他回答

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

首先将list更改为numpy数组,并像这样做:print(np.linalg.norm(np.array(a) - np.array(b)))。第二种方法直接从python列表as: print(np.linalg.norm(np.subtract(a,b)))

使用numpy.linalg.norm:

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

这是因为欧氏距离是l2范数,而numpy.linalg.norm中ord参数的默认值是2。 要了解更多理论,请参阅数据挖掘介绍:

从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
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)

对于那些对一次计算多个距离感兴趣的人来说,我已经使用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")