高效计算Pandas DataFrame经纬度坐标点间距离的方法
经纬度距离批量计算方案
核心结论
- 总计算量为30栋建筑×30000个城市=90万次配对计算,量级很小,完全可以实现。
- 不推荐直接用Geopy逐行循环计算:Geopy的测地线距离精度高,但纯Python逐行循环跑90万次耗时可达40~60秒,效率很低。优先选择向量化计算方案,耗时不到0.1秒,完全满足城市级距离计算的精度要求。
最优实现代码(向量化Haversine公式)
Haversine是计算球面两点距离的经典公式,对于城市级距离计算,误差在米级,完全够用,配合numpy向量化运算速度极快。
import pandas as pd import numpy as np # ---------------------- # 此处复用你已有的df1、df2定义即可 # df1 = pd.DataFrame(...) # df2 = pd.DataFrame(...) # ---------------------- # 1. 生成笛卡尔积:配对所有建筑和城市的经纬度 df1['tmp_key'] = 1 df2['tmp_key'] = 1 cross_df = pd.merge( df1, df2, on='tmp_key', suffixes=('', '_city') # 城市经纬度列加后缀区分 ).drop('tmp_key', axis=1) # 2. 定义向量化距离计算函数,返回单位为公里 def calc_haversine(lat1, lon1, lat2, lon2): # 经纬度角度转弧度 lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2]) dlat = lat2 - lat1 dlon = lon2 - lon1 a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2 c = 2 * np.arcsin(np.sqrt(a)) return c * 6371 # 地球平均半径取6371km # 批量计算所有配对的距离 cross_df['Distance'] = calc_haversine( cross_df['Latitude'], cross_df['Longitude'], cross_df['Latitude_city'], cross_df['Longitude_city'] ) # 3. 整理为你需要的输出结构 output_df = cross_df[['City', 'Building', 'Latitude', 'Longitude', 'Distance']] output_df = output_df.set_index(['City', 'Building'])
若需使用Geopy高精度计算的优化方案
如果你需要WGS84椭球模型下的更高精度距离,不要写双层for循环逐行调用Geopy,配合并行计算可以把耗时压缩到3~5秒:
from geopy.distance import geodesic import swifter # 需提前安装:pip install swifter # 先执行前面的笛卡尔积步骤得到cross_df,再运行以下代码 cross_df['Distance'] = cross_df.swifter.apply( lambda row: geodesic( (row['Latitude'], row['Longitude']), (row['Latitude_city'], row['Longitude_city']) ).km, axis=1 ) # 后续整理输出结构的步骤和前面一致
耗时参考
- 纯Python双层循环+Geopy:40~60秒
- 并行apply+Geopy:3~5秒
- 向量化Haversine公式:<0.1秒,90万次计算瞬时完成
内容的提问来源于stack exchange,提问作者092374
相关产品推荐
相关产品推荐

