在使用harversine公式计算两个点距离时,若数据量少可以直接使用geopy库或者手动实现该公式。附代码如下:
def haversine(lat1, lon1, lat2, lon2):
"""
计算两个经纬度点之间的距离(单位:米)
"""
R = 6371000 # 地球半径(单位:米)
phi1 = np.radians(lat1)
phi2 = np.radians(lat2)
delta_phi = np.radians(lat2 - lat1)
delta_lambda = np.radians(lon2 - lon1)
a = np.sin(delta_phi / 2) ** 2 + np.cos(phi1) * np.cos(phi2) * np.sin(delta_lambda / 2) ** 2
c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
distance = R * c
return distance
当数据量比较多时,就会出现计算效率的问题,采用对数据进行分批次的处理,然后采用线程池的方式,提高计算速度。
另外结合numpy有极佳的效果。
def haversine_vectorized(lon1, lat1, lon2, lat2):
# 转换为弧度
lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
# Haversine 公式
dlon = lon2 - lon1
dlat = lat2 - lat1
a = np.sin(dlat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2) ** 2
c = 2 * np.arcsin(np.sqrt(a))
# 地球半径 (公里)
r = 6371
return c * r
batch_size = 1000
# 将合并后的 DataFrame 分成多个批次
batches = [merged_df.iloc[i:i + batch_size] for i in range(0, len(merged_df), batch_size)]
all_results = []
# 使用 ProcessPoolExecutor 进行批次并行计算
with concurrent.futures.ProcessPoolExecutor() as executor:
futures = {executor.submit(calculate_distances, batch): batch for batch in batches}
for future in concurrent.futures.as_completed(futures):
result = future.result()
all_results.extend(result)