基于含经纬度的CSV文件生成酒店间距离矩阵技术求助
生成地点间实际距离矩阵的解决方案
你之前的代码仅计算了纬度的差值,没有考虑经纬度结合的球面实际距离。要生成真实的地点间距离矩阵,需要基于地球球面/椭球模型计算两点间的最短距离,以下是几种实用的实现方式:
方法1:手动实现Haversine公式
Haversine公式是计算球面两点间最短距离的经典方法,适合自定义需求:
import numpy as np import pandas as pd # 读取CSV数据(替换为你的文件路径) df = pd.read_csv("locations.csv") def haversine(lat1, lon1, lat2, lon2): # 将角度转为弧度 lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2]) # 计算经纬度差值 dlat = lat2 - lat1 dlon = lon2 - lon1 # Haversine核心计算逻辑 a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2 c = 2 * np.arcsin(np.sqrt(a)) # 地球平均半径(单位:公里,换成3956可得到英里结果) earth_radius = 6371 return c * earth_radius # 提取经纬度数组 coords = df[["latitude", "longitude"]].values # 初始化距离矩阵 distance_matrix = np.zeros((len(coords), len(coords))) # 遍历计算每对地点的距离 for i in range(len(coords)): for j in range(len(coords)): distance_matrix[i, j] = haversine(coords[i,0], coords[i,1], coords[j,0], coords[j,1]) # 转换为带地点名称的DataFrame distance_df = pd.DataFrame(distance_matrix, index=df["name"], columns=df["name"]) # 合并原名称列与距离矩阵(保持和你原代码类似的输出格式) final_df = pd.concat([df[["name"]], distance_df], axis=1)
方法2:用Scipy实现向量化计算(更高效)
利用scipy.spatial.distance.cdist实现向量化计算,避免嵌套循环,处理大量数据时速度更快:
import numpy as np import pandas as pd from scipy.spatial.distance import cdist df = pd.read_csv("locations.csv") def haversine_vec(latlon_pair1, latlon_pair2): lat1, lon1 = latlon_pair1 lat2, lon2 = latlon_pair2 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 6371 * c coords = df[["latitude", "longitude"]].values # 直接生成距离矩阵 distance_matrix = cdist(coords, coords, metric=haversine_vec) distance_df = pd.DataFrame(distance_matrix, index=df["name"], columns=df["name"]) final_df = pd.concat([df[["name"]], distance_df], axis=1)
方法3:用Geopy库(更简洁准确)
Geopy的geodesic方法基于WGS-84椭球模型计算距离,比纯球面模型更接近真实地球的形状,精度更高:
import pandas as pd from scipy.spatial.distance import cdist from geopy.distance import geodesic df = pd.read_csv("locations.csv") def geopy_dist(latlon_pair1, latlon_pair2): # geodesic接受(lat, lon)格式的元组,返回距离对象,.km转为公里单位 return geodesic(latlon_pair1, latlon_pair2).km coords = df[["latitude", "longitude"]].values distance_matrix = cdist(coords, coords, metric=geopy_dist) distance_df = pd.DataFrame(distance_matrix, index=df["name"], columns=df["name"]) final_df = pd.concat([df[["name"]], distance_df], axis=1)
注意事项
- 单位转换:如果需要英里结果,Haversine方法将地球半径改为3956;Geopy方法把
.km换成.miles即可。 - 精度选择:对距离准确性要求高的场景,优先用Geopy的
geodesic方法。
内容的提问来源于stack exchange,提问作者dfouheqoijefoih
相关产品推荐
相关产品推荐

