Python 用numpy计算欧氏距离

Python 用numpy计算欧氏距离,python,numpy,Python,Numpy,我有一个点集,我把它的坐标存储在三个不同的数组中(xa,ya,za)。现在,我想计算这个点集的每个点(xa[0]、ya[0]、za[0]等等)与另一个点集(xb、yb、zb)的所有点之间的欧氏距离,每次都将最小距离存储在一个新数组中 假设xa.shape=(11,),ya.shape=(11,),za.shape=(11,)。分别是xb.shape=(13,),yb.shape=(13,),zb.shape=(13,)。我想做的是每次取一个xa[],ya[],za[],并计算它与xb,yb,zb

我有一个点集,我把它的坐标存储在三个不同的数组中(xa,ya,za)。现在,我想计算这个点集的每个点(xa[0]、ya[0]、za[0]等等)与另一个点集(xb、yb、zb)的所有点之间的欧氏距离,每次都将最小距离存储在一个新数组中

假设xa.shape=(11,),ya.shape=(11,),za.shape=(11,)。分别是xb.shape=(13,),yb.shape=(13,),zb.shape=(13,)。我想做的是每次取一个xa[],ya[],za[],并计算它与xb,yb,zb的所有元素的距离,最后将最小值存储到xfinal.shape=(11,)数组中


你认为numpy可以做到这一点吗?

你可以用
np.subtract.outer(xa,xb)
计算每个xa到每个xb的差值。到最近xb的距离由下式给出

np.min(np.abs(np.subtract.outer(xa, xb)), axis=1)
要将此扩展到3D

distances = np.sqrt(np.subtract.outer(xa, xb)**2 + \
    np.subtract.outer(ya, yb)**2 + np.subtract.outer(za, zb)**2)
distance_to_nearest = np.min(distances, axis=1)
如果您确实想知道哪一个b点最近,可以使用
argmin
代替
min

index_of_nearest = np.argmin(distances, axis=1)

您可以使用
np.subtract.outer(xa,xb)
计算每个xa到每个xb的差值。到最近xb的距离由下式给出

np.min(np.abs(np.subtract.outer(xa, xb)), axis=1)
要将此扩展到3D

distances = np.sqrt(np.subtract.outer(xa, xb)**2 + \
    np.subtract.outer(ya, yb)**2 + np.subtract.outer(za, zb)**2)
distance_to_nearest = np.min(distances, axis=1)
如果您确实想知道哪一个b点最近,可以使用
argmin
代替
min

index_of_nearest = np.argmin(distances, axis=1)

另一种解决方案是使用scipy的空间模块,尤其是KDTree

此类从一组数据中学习,并可在给定新数据集时进行查询:

from scipy.spatial import KDTree
# create some fake data
x = arange(20)
y = rand(20)
z = x**2
# put them togheter, should have a form [n_points, n_dimension]
data = np.vstack([x, y, z]).T
# create the KDTree
kd = KDTree(data)
现在,如果您有一个点,您可以通过以下操作简单地询问壁橱点(或N个最近点)的距离和索引:

kd.query([1, 2, 3])
# (1.8650720813822905, 2)
# your may differs
或者,给定一系列位置:

#bogus position
x2 = rand(20)*20
y2 = rand(20)*20
z2 = rand(20)*20
# join them togheter as the input
data2 = np.vstack([x2, y2, z2]).T
#query them
kd.query(data2)

#(array([ 14.96118553,   9.15924813,  16.08269197,  21.50037074,
#    18.14665096,  13.81840533,  17.464429  ,  13.29368755,
#    20.22427196,   9.95286671,   5.326888  ,  17.00112683,
#     3.66931946,  20.370496  ,  13.4808055 ,  11.92078034,
#     5.58668204,  20.20004206,   5.41354322,   4.25145521]),
#array([4, 3, 2, 4, 2, 2, 4, 2, 3, 3, 2, 3, 4, 4, 3, 3, 3, 4, 4, 4]))

另一种解决方案是使用scipy的空间模块,尤其是KDTree

此类从一组数据中学习,并可在给定新数据集时进行查询:

from scipy.spatial import KDTree
# create some fake data
x = arange(20)
y = rand(20)
z = x**2
# put them togheter, should have a form [n_points, n_dimension]
data = np.vstack([x, y, z]).T
# create the KDTree
kd = KDTree(data)
现在,如果您有一个点,您可以通过以下操作简单地询问壁橱点(或N个最近点)的距离和索引:

kd.query([1, 2, 3])
# (1.8650720813822905, 2)
# your may differs
或者,给定一系列位置:

#bogus position
x2 = rand(20)*20
y2 = rand(20)*20
z2 = rand(20)*20
# join them togheter as the input
data2 = np.vstack([x2, y2, z2]).T
#query them
kd.query(data2)

#(array([ 14.96118553,   9.15924813,  16.08269197,  21.50037074,
#    18.14665096,  13.81840533,  17.464429  ,  13.29368755,
#    20.22427196,   9.95286671,   5.326888  ,  17.00112683,
#     3.66931946,  20.370496  ,  13.4808055 ,  11.92078034,
#     5.58668204,  20.20004206,   5.41354322,   4.25145521]),
#array([4, 3, 2, 4, 2, 2, 4, 2, 3, 3, 2, 3, 4, 4, 3, 3, 3, 4, 4, 4]))

实现这一点的方法不止一种。最重要的是,内存使用率和速度之间需要权衡。下面是一个浪费的方法:

s = (1, -1)
d = min((xa.reshape(s)-xb.reshape(s).T)**2
     + (ya.reshape(s)-yb.reshape(s).T)**2
     + (za.reshape(s)-zb.reshape(s).T)**2), axis=0)

另一种方法是迭代
b
中的点集,以避免扩展到完整的矩阵。

有多种方法。最重要的是,内存使用率和速度之间需要权衡。下面是一个浪费的方法:

s = (1, -1)
d = min((xa.reshape(s)-xb.reshape(s).T)**2
     + (ya.reshape(s)-yb.reshape(s).T)**2
     + (za.reshape(s)-zb.reshape(s).T)**2), axis=0)

另一种方法是迭代
b
中设置的点,以避免扩展到完整的矩阵。

换句话说,对于每个
xa/ya/za
,您希望计算到
xb/yb/zb
中最近点的距离?是的,如果某种程度上更容易…换句话说,对于每个
xa/ya/za
,你想计算到最近点的距离,在
xb/yb/zb
?是的,如果它更容易的话…是的,我认为它是可行的。看起来很快。我的阵列很大!因此,我认为我必须遍历xa,ya,za的长度,取每一行,用整个xb,yb,zb计算它的距离。我认为它有效。我会反复核对它的有效性,然后告诉你。无论如何,非常感谢你!如果你能使用scipy,请参阅@EnricoGiampieri的公式。不幸的是,它说数组太大了。它似乎对我的数组不起作用。是的,我认为它起作用了。看起来很快。我的阵列很大!因此,我认为我必须遍历xa,ya,za的长度,取每一行,用整个xb,yb,zb计算它的距离。我认为它有效。我会反复核对它的有效性,然后告诉你。无论如何,非常感谢你!如果你能使用scipy,请参阅@EnricoGiampieri的公式。不幸的是,它说数组太大了。它似乎对我的数组不起作用。与其他答案相比,它有很大的优势,你也可以使用更快的cKDTree(使用新的scipy,它可能是相同的)。好的,显然,这个选项效果更好。然而,最后我不知道这在我运行这些脚本的abaqus中是否有效。您知道如何从kd.query中提取具有最小值的数组吗?事先多谢。好的,我做到了。这并不难。再次非常感谢。与其他答案相比,您还可以使用更快的cKDTree(与新的scipy可能相同)。显然,此选项效果更好。然而,最后我不知道这在我运行这些脚本的abaqus中是否有效。您知道如何从kd.query中提取具有最小值的数组吗?事先多谢。好的,我做到了。这并不难。再次非常感谢。