如何计算DataFrame中坐标数量不同的两条路线的距离差异?
路线相似度判断:不等长坐标序列的公里数差异计算方案
针对存储不等长[纬度,经度]坐标序列的DataFrame,要判断实际路线与预估路线的关系,核心解决不等长轨迹的空间匹配问题,以下是可落地的步骤:
一、基础预处理:统一坐标系与单路线长度计算
先确保所有坐标采用WGS84(GPS通用坐标系),再计算单条路线的总行驶公里数:
- 对每条路线的连续坐标点,用Haversine公式(或精度更高的Vincenty公式)计算两点间的地理距离(单位:公里)
- 累加所有连续点的距离,得到单条路线的总长度
Python实现示例:
import math def haversine(coord1, coord2): # 坐标格式:[纬度, 经度],单位:度 lat1, lon1 = coord1 lat2, lon2 = coord2 R = 6371 # 地球半径(公里) dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = math.sin(dlat/2)**2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon/2)**2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) return R * c # 返回两点间公里数 def route_total_length(route_coords): total = 0.0 for i in range(len(route_coords)-1): total += haversine(route_coords[i], route_coords[i+1]) return total
二、核心:不等长路线的空间相似度计算
由于两条路线的点数量不一致,无法直接点对点对比,推荐结合以下三种方法判断:
1. 弗雷歇距离(Fréchet Distance)
衡量两条曲线的「最大最小贴合距离」——直观来说,就是一人走路线A、狗走路线B时,能让两者始终相连的最短绳长的最大值,能精准反映路线的整体贴合度。
简化版Python实现:
def frechet_distance(P, Q): n = len(P) m = len(Q) # 预计算所有点对的距离矩阵 dist_matrix = [[haversine(P[i], Q[j]) for j in range(m)] for i in range(n)] # 动态规划求解弗雷歇距离 dp = [[0.0 for _ in range(m)] for _ in range(n)] dp[0][0] = dist_matrix[0][0] # 初始化边界 for i in range(1, n): dp[i][0] = max(dp[i-1][0], dist_matrix[i][0]) for j in range(1, m): dp[0][j] = max(dp[0][j-1], dist_matrix[0][j]) # 填充DP表 for i in range(1, n): for j in range(1, m): dp[i][j] = max(min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]), dist_matrix[i][j]) return dp[-1][-1]
2. 动态时间规整(DTW)
将两条不等长的坐标序列做最优对齐,找到最匹配的点对应关系,再计算对齐后的平均距离,适合路径趋势一致但采样点密度不同的场景。
用dtw库实现(需先安装:pip install dtw):
from dtw import dtw import numpy as np def dtw_route_avg_distance(P, Q): P_np = np.array(P) Q_np = np.array(Q) # 以Haversine距离为度量标准做对齐 total_dist, _, _, path = dtw(P_np, Q_np, dist=lambda x, y: haversine(x, y)) # 返回对齐后的平均距离(公里) return total_dist / len(path[0])
3. 投影距离总和
将一条路线的每个点,投影到另一条路线的最近线段上,计算所有投影点与原有点的距离之和,反映整体偏离程度:
- 遍历路线A的每个点,找到路线B中距离该点最近的线段
- 计算点到线段的垂直距离,累加所有距离后取平均值
三、分类判断逻辑
结合总长度差异与空间相似度指标,设定可调整的阈值(根据业务场景灵活修改):
- 同一条路线:总长度差异<5%,弗雷歇距离<0.05公里(50米),投影平均距离<0.02公里(20米)
- 相似路线:总长度差异5%-20%,弗雷歇距离0.05-0.2公里(50-200米),投影平均距离0.02-0.1公里(20-100米)
- 完全不同路线:总长度差异>20%,或弗雷歇距离>0.2公里,或投影平均距离>0.1公里
示例计算
针对你给出的示例数据:
estimated_route = [[-12.11149, -77.04675], [-12.11145, -77.04671], [-12.11139, -77.04664], [-12.11134, -77.04659], [-12.11123, -77.04648], [-12.11122, -77.04646], [-12.11122, -77.04646], [-12.1118, -77.04589], [-12.11193, -77.04576]] real_route = [[-12.111973, -77.047275], [-12.111933, -77.047236], [-12.111811, -77.047122], [-12.111683, -77.046984]] # 计算总长度 est_len = route_total_length(estimated_route) # 约0.12公里 real_len = route_total_length(real_route) # 约0.035公里 # 总长度差异:(0.12-0.035)/0.035 ≈ 242%,远大于20%,直接判定为完全不同路线
内容的提问来源于stack exchange,提问作者alfonsomore
相关产品推荐
相关产品推荐

