如何在不使用嵌套循环的情况下计算DataFrame中所有点对的距离?
问题描述
用户创建了如下示例DataFrame:
import pandas as pd data = {'X': [10,20,30,40,50,60,70,80,90], 'Y': [1,2,3,4,5,6,7,8,9], } df_test = pd.DataFrame(data)
需要计算数据集中所有点对的距离(即每个点与其他所有点的距离),已定义欧氏距离函数:
import numpy as np def dist(X1,Y1,X2,Y2): # 计算两点间距离 d = np.sqrt((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1)) return d
最初使用嵌套for循环实现,但该方法在大数据集下效率极低甚至导致崩溃(注:原代码存在列名错误、结果未正确收集的问题,已修正):
res = [] for i in range(0,len(df_test)): X1 = df_test.X[i] Y1 = df_test.Y[i] for j in range(0,len(df_test)): X2 = df_test.X[j] Y2 = df_test.Y[j] res.append(dist(X1,Y1,X2,Y2)) print(res[-1]) print()
无嵌套循环的高效解决方案
以下两种方法均基于向量运算,避免了Python层面的循环,大幅提升计算效率,适合大数据集:
方法1:利用NumPy广播机制
将DataFrame转换为NumPy数组后,通过广播实现批量计算:
import numpy as np import pandas as pd # 转换为NumPy数组,形状为(N, 2) points = df_test.to_numpy() # 利用广播计算所有点对的欧氏距离 # points[:, np.newaxis] 将形状变为(N, 1, 2),与原数组广播为(N, N, 2) # 计算差值平方和后开根号,得到N×N的距离矩阵 distances = np.sqrt(np.sum((points[:, np.newaxis] - points)**2, axis=2)) # 输出结果矩阵 print(distances)
distances[i][j]对应第i个点与第j个点的距离,矩阵为对称矩阵(distances[i][j] = distances[j][i]),对角线为点到自身的距离0。
方法2:使用Scipy的封装函数
Scipy提供了专门的距离计算工具,代码更简洁且优化程度高:
from scipy.spatial.distance import pdist, squareform # pdist计算所有两两不同点对的距离(返回一维数组,长度为N*(N-1)/2) # squareform将其转换为对称的N×N距离矩阵 distances = squareform(pdist(df_test, metric='euclidean')) print(distances)
metric='euclidean'指定计算欧氏距离,Scipy还支持其他距离类型(如曼哈顿距离、余弦距离等),只需修改参数即可。
内容的提问来源于stack exchange,提问作者Wishwa Rathnaweera
相关产品推荐
相关产品推荐

