使用Vincenty公式计算Pandas DataFrame连续点距离报错排查
解决Pandas中计算连续点Vincenty距离的ValueError问题
这个问题我之前也碰到过,本质是vincenty函数没办法直接处理Pandas Series对象,咱们一步步拆解原因和解决方法:
为啥会报错?
你写的代码里,直接把(df['lat'],df['long'])和(df['lat'].shift(-1), df['long'].shift(-1))传给vincenty,但这个函数只认单个的经纬度坐标对(比如(39.985, 116.307)),或者一组结构化的坐标对序列。当它拿到Series的时候,内部做有效性检查时会触发布尔判断,而Series的布尔判断返回的是一个布尔数组,这就导致了"真值歧义"的错误。
另外提一句:现在vincenty已经被geopy官方弃用了,推荐用geodesic替代,用法完全一样,还能避免警告。
两种可行的解决方法
方法1:打包坐标对批量计算(效率更高)
先把所有坐标点打包成列表,再和下一个点的列表配对,用列表推导逐对计算:
from geopy.distance import geodesic # 替代vincenty import pandas as pd import numpy as np # 你的示例数据 data = { 'lat': [39.9852833333333, 39.9852166666667, 39.9851333333333, 39.9850666666667, 39.9847333333333], 'long': [116.307367, 116.309550, 116.309767, 116.309883, 116.309933] } df = pd.DataFrame(data) # 生成当前点和下一个点的坐标列表 current_points = list(zip(df['lat'], df['long'])) # 下一个点列表:从第二个点开始,最后补个None(最后一个点没后续) next_points = current_points[1:] + [None] # 计算距离,最后一行设为NaN df['distance'] = [geodesic(p, np).meters if np is not None else np.nan for p, np in zip(current_points, next_points)]
方法2:用apply逐行处理(逻辑更直观)
通过apply遍历每一行,根据行索引获取下一行的坐标来计算:
from geopy.distance import geodesic import pandas as pd import numpy as np # 同上的data和df定义 def calc_row_distance(row): # 如果是最后一行,直接返回NaN(没有下一个点) if row.name == len(df) - 1: return np.nan # 获取下一行的经纬度 next_lat = df.loc[row.name + 1, 'lat'] next_lon = df.loc[row.name + 1, 'long'] # 计算距离,这里用米为单位,换成.kilometers/.miles都可以 return geodesic((row['lat'], row['long']), (next_lat, next_lon)).meters df['distance'] = df.apply(calc_row_distance, axis=1)
最终效果
运行后df['distance']列就会显示连续两点间的距离,最后一行因为没有后续点,值为NaN,完美解决之前的报错问题~
内容的提问来源于stack exchange,提问作者Asif Khan
相关产品推荐
相关产品推荐

