Python实现两个DataFrame间的Haversine交叉距离矩阵及最近位置查找
计算人员与城市间的Haversine交叉距离矩阵及最近城市
实现思路
针对1000+人员和300+城市的规模,使用numpy向量化运算实现Haversine公式,避免循环带来的效率问题,快速生成交叉距离矩阵并提取最近城市信息。
步骤1:定义Haversine距离函数
该函数用于计算两组经纬度之间的球面距离(单位:公里),基于numpy实现向量化计算:
import numpy as np import pandas as pd def haversine(lat1, lon1, lat2, lon2): # 转换经纬度为弧度(numpy三角函数基于弧度计算) lat1_rad = np.radians(lat1) lon1_rad = np.radians(lon1) lat2_rad = np.radians(lat2) lon2_rad = np.radians(lon2) # Haversine核心计算 dlat = lat2_rad - lat1_rad dlon = lon2_rad - lon1_rad a = np.sin(dlat/2)**2 + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(dlon/2)**2 c = 2 * np.arcsin(np.sqrt(a)) # 地球平均半径(公里) earth_radius = 6371 return c * earth_radius
步骤2:加载输入数据
# 城市数据 city_data = {'City': ['Delhi', 'Mumbai'], 'Lat': [28.7041, 19.0760], 'Long':[77.1025,72.8777] } # 人员数据 person_data = {'City': ['A', 'B'], 'Lat': [12.9716, 13.0827], 'Long':[77.5946,80.2707] } df_city = pd.DataFrame(city_data) df_person = pd.DataFrame(person_data)
步骤3:生成交叉距离矩阵(Output-1)
通过numpy广播机制,一次性计算所有人员与城市的距离组合,效率远高于循环遍历:
# 提取经纬度数组 person_lats = df_person['Lat'].values person_lons = df_person['Long'].values city_lats = df_city['Lat'].values city_lons = df_city['Long'].values # 广播计算所有人员-城市对的距离 distance_matrix = haversine(person_lats[:, np.newaxis], person_lons[:, np.newaxis], city_lats, city_lons) # 转换为结构化DataFrame df_distance = pd.DataFrame( distance_matrix, index=df_person['City'], # 行:人员 columns=df_city['City'] # 列:城市 ) print("Output-1: 交叉距离矩阵(单位:公里)") print(df_distance)
示例输出:
Output-1: 交叉距离矩阵(单位:公里) City Delhi Mumbai A 1705.736532 711.743874 B 1680.034949 1013.437677
步骤4:找出每个人员的最近城市(Output-2)
通过DataFrame的idxmin和min方法,快速提取每行(人员)的最小距离及对应城市:
# 获取最近城市名称和最小距离 closest_city = df_distance.idxmin(axis=1) min_distance = df_distance.min(axis=1) # 整理结果DataFrame df_closest = pd.DataFrame({ 'Person': closest_city.index, 'Closest_City': closest_city.values, 'Min_Distance_km': min_distance.values }) print("\nOutput-2: 每个人员对应的最近城市") print(df_closest)
示例输出:
Output-2: 每个人员对应的最近城市 Person Closest_City Min_Distance_km 0 A Mumbai 711.743874 1 B Delhi 1680.034949
内容的提问来源于stack exchange,提问作者Rohan Bali
相关产品推荐
相关产品推荐

