计算坐标列表之间的距离矩阵(NumPy向量化实现)

使用scipy的cdist函数可高效、向量化地计算二维坐标点集的欧氏距离矩阵,避免显式循环,适用于中大规模数据。

在科学计算与机器学习中,经常需要计算一组坐标点两两之间的欧氏距离,构成对称的距离矩阵(distance matrix)。手动嵌套循环不仅代码冗长,且性能低下;而借助 NumPy 的向量化能力结合 SciPy 提供的成熟工具,可实现简洁、高效、可扩展的解决方案。

推荐使用 scipy.spatial.distance.cdist —— 它专为成对距离计算设计,支持多种距离度量(默认为欧氏距离),底层基于优化的 C 实现,速度远超纯 Python 或朴素 NumPy 广播方案。

以下是一个完整示例:

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

# 原始坐标列表(可为 tuple 或 list)
l_coords = [(1, 2), (1.1, 2.2), (1.05, 1.9)]

# 转换为二维 NumPy 数组(n×d,n=点数,d=维度)
coords = np.array(l_coords)

# 计算距离矩阵:每行i、列j表示 coords[i] 到 coords[j] 的距离
dist_matrix = cdist(coords, coords, metric='euclidean')

print(dist_matrix)

输出:

[[0.         0.2236068  0.1118034 ]
 [0.2236068  0.         0.30413813]
 [0.1118034  0.30413813 0.        ]]

关键说明

  • cdist(X, Y) 返回形状为 (len(X), len(Y)) 的矩阵;当 X == Y 时,结果为对称方阵,对角线全为 0;
  • 输入自动支持 list、tuple、np.ndarray,但建议显式转为 np.array 以确保类型与维度清晰;
  • 支持其他 metric 参数,如 'manhattan'、'cosine'、'sqeuclidean' 等;
  • 若仅需上三角或避免重复计算,可后续用 np.triu(dist_matrix, k=1) 提取非对角上三角部分。

⚠️ 注意事项

  • cdist 不属于 NumPy 原生模块,需额外安装 SciPy(pip install scipy);
  • 对于超大规模点集(如 >10⁵ 点),内存可能成为瓶颈(距离矩阵为 O(n²) 空间复杂度),此时应考虑近似算法或分块计算;
  • 如项目已依赖 scikit-learn,也可用 sklearn.metrics.pairwise_distances,接口类似,但默认行为略有差异(例如对稀疏输入更友好)。

综上,scipy.spatial.distance.cdist 是计算坐标距离矩阵最实用、高效且可读性强的标准方案。