如何从多个shape为(300,)的numpy数组中找出最接近的两个数组?
找出数组集中彼此最接近的两个数组
当然有办法!其实你可以基于已经熟悉的scipy.spatial.distance.cdist来实现,不过需要做一点额外的处理,另外也有更高效的方法,我给你分两种情况说明:
方法一:基于cdist的基础实现
如果你不想引入新工具,用cdist完全能搞定:
- 首先把所有(300,)的数组堆叠成一个形状为
(N, 300)的二维numpy数组,假设叫arrays_stack(N是数组的总数) - 用
cdist计算所有数组间的距离矩阵,得到一个(N, N)的矩阵dist_matrix - 因为距离矩阵是对称的,且对角线是数组自身的距离(为0),所以我们先把对角线的值设为无穷大,避免选中同一个数组
- 最后找出矩阵中最小值对应的索引,就是彼此最接近的两个数组的位置
代码示例:
import numpy as np from scipy.spatial.distance import cdist # 模拟生成5个(300,)的数组,替换成你自己的数组即可 arrays = [np.random.rand(300) for _ in range(5)] arrays_stack = np.vstack(arrays) # 计算距离矩阵,这里用欧氏距离,你可以换成其他支持的度量(比如曼哈顿距离) dist_matrix = cdist(arrays_stack, arrays_stack, metric='euclidean') # 把对角线设为无穷大,排除自身对比 np.fill_diagonal(dist_matrix, np.inf) # 找到最小距离对应的数组索引 min_idx = np.unravel_index(np.argmin(dist_matrix), dist_matrix.shape) closest_pair = (arrays[min_idx[0]], arrays[min_idx[1]]) print(f"最接近的两个数组是索引{min_idx[0]}和{min_idx[1]}")
方法二:更高效的KD-Tree实现
如果你的数组数量特别多(比如上千个甚至更多),cdist的O(N²)复杂度会有点慢,这时候可以用scipy.spatial.KDTree来优化查询效率:
- 同样先把数组堆叠成二维数组
- 构建KD-Tree后,用
query方法找每个点的最近邻(排除自身),再从所有最近邻距离中筛选出全局最小的那一对
代码示例:
import numpy as np from scipy.spatial import KDTree # 模拟生成数组,替换成你的数据 arrays = [np.random.rand(300) for _ in range(5)] arrays_stack = np.vstack(arrays) tree = KDTree(arrays_stack) # k=2表示找每个点的前2个最近点(第一个是自身),所以取索引1的结果就是除自身外的最近邻 distances, indices = tree.query(arrays_stack, k=2) # 找到所有最近邻距离中的最小值对应的数组对 min_dist_idx = np.argmin(distances[:, 1]) pair_idx = (min_dist_idx, indices[min_dist_idx, 1]) closest_pair = (arrays[pair_idx[0]], arrays[pair_idx[1]]) print(f"最接近的两个数组是索引{pair_idx[0]}和{pair_idx[1]}")
注意:如果存在多组距离相同且均为最小值的点对,上面的方法会返回第一个遇到的那一对;如果需要获取所有这样的点对,可以额外添加逻辑筛选。
内容的提问来源于stack exchange,提问作者Kabilesh
相关产品推荐
相关产品推荐

