Python中缺少值的两组点之间的快速欧几里得距离

时间:2018-08-21 10:32:28

标签: python numpy scipy

我有两个numpy矩阵X和Y分别代表某个d维空间中的一组点。我想计算从X中的每个点到Y中的每个点的所有欧几里得距离。scipy provides the function cdist确实做到了这一点,但有一个陷阱:有些点包含NaN形式的缺失值。我希望距离运算忽略NaN条目,例如,如果我正在计算以下两个点之间的距离

a = [1, 3, nan]
b = [2, nan, 4]

然后我将忽略第二维和第三维,从而得到sqrt((1-2)**2) = 1的距离。

不幸的是,在此设置中,只要在一对点中找到单个NaN,cdist就会返回NaN距离。 euclidean_distances function in scikit-learn

也是如此

当然可以编写一个双循环来执行所有必需的操作,但是由于X和Y是大型矩阵,因此结果太慢了。因此,基于numpy / scipy的解决方案将是理想的。

numpy确实包含一些机制,例如masked arrays,这些机制允许执行忽略NaN值的操作,但是scipy似乎忽略了这些掩码。

执行此操作的有效方法是什么?

2 个答案:

答案 0 :(得分:3)

最简单的方法是使用标准的欧几里德距离公式,但将sum替换为nansum

np.sqrt(np.nansum((X - Y)**2))

我怀疑您会得到比这更容易的东西(您必须自己进行广播,因为您只提供了1d输入)。标准做法是nan始终通过计算进行。

答案 1 :(得分:1)

使用@Daniel F的建议,您可以像这样使用cdist:

cdist(XA, XB, lambda u, v: np.sqrt(np.nansum((u-v)**2)))

例如:

import numpy as np
from scipy.spatial.distance import cdist, squareform

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

print(np.sqrt(np.nansum((a-b)**2)))

输出:

1.0

上面的示例只是为了演示lambda函数的作用。