如何高效在Pandas DataFrame中应用math.dist()计算距离
问题
现有如下结构的DataFrame(df):
Name Point1 Point2 name1 '[x_coord, y_coord]' '[x_coord, y_coord]' name2 '[x_coord, y_coord]' '[x_coord, y_coord]' name3 '[x_coord, y_coord]' '[x_coord, y_coord]' ...
需要新增一列Distance,计算每行Point1和Point2两点间的欧氏距离,预期逻辑为math.dist(ast.literal_eval(df['Point1']), ast.literal_eval(df['Point2'])),但遇到以下问题:
- 直接执行
df['Distance'] = math.dist(ast.literal_eval(df['Point1']), ast.literal_eval(df['Point2']))无法生效 - 使用列表推导式循环
itertuples的方法可行,但百万级数据量下速度极慢:dist_list = [math.dist(ast.literal_eval(row[2]), ast.literal_eval(row[3])) for row in df.itertuples()] - 自定义函数结合
apply的方式速度同样不理想:def get_dist(p1: str, p2: str): return math.dist(ast.literal_eval(p1), ast.literal_eval(p2)) df['Distance'] = df.apply(lambda x: get_dist(x['Point1'], x['Point2']), axis=1)
同时,还拥有4个浮点型坐标列:Xcoord_point1, Ycoord_point1, Xcoord_point2, Ycoord_point2,可用于优化。
高效解决方案
方案一:直接利用已有坐标列(最优)
既然已经有拆分好的浮点型坐标列,无需处理字符串格式的Point1/Point2,直接用矢量运算计算欧氏距离,这是百万级数据下最快的方式:
方法1:手动计算平方和开根号
import numpy as np df['Distance'] = np.sqrt( (df['Xcoord_point1'] - df['Xcoord_point2'])**2 + (df['Ycoord_point1'] - df['Ycoord_point2'])**2 )
方法2:使用numpy的hypot函数(更简洁)
df['Distance'] = np.hypot( df['Xcoord_point1'] - df['Xcoord_point2'], df['Ycoord_point1'] - df['Ycoord_point2'] )
两种方法均为纯矢量运算,无逐行循环,速度比任何逐行处理方式快数个数量级。
方案二:优化字符串坐标列的处理(必须使用Point1/Point2时)
如果必须基于字符串格式的坐标列计算,可通过pandas字符串方法批量解析,避免逐行调用ast.literal_eval:
步骤1:批量解析字符串坐标
# 解析Point1的x、y坐标 df[['p1_x', 'p1_y']] = df['Point1'].str.strip('[]').str.split(',', expand=True).astype(float) # 解析Point2的x、y坐标 df[['p2_x', 'p2_y']] = df['Point2'].str.strip('[]').str.split(',', expand=True).astype(float)
步骤2:矢量计算距离
用numpy的矢量运算计算距离:
df['Distance'] = np.hypot(df['p1_x'] - df['p2_x'], df['p1_y'] - df['p2_y'])
这种批量解析+矢量计算的组合,效率远高于循环或apply方法。
内容的提问来源于stack exchange,提问作者fschuch
相关产品推荐
相关产品推荐

