如何从Pandas DataFrame滚动窗口获取两列值计算飞行航点距离
解决Pandas Rolling结合Haversine距离计算的数组维度问题
问题根源
当设置raw=True时,Pandas的rolling(window=2)会将窗口内的2行2列数据展平为一维数组(比如窗口包含[lat1, lon1]和[lat2, lon2]时,传入函数的是[lat1, lon1, lat2, lon2]),但你的haversine_distance函数是按二维数组的索引逻辑编写的,自然会报错。
解决方案1:修改函数适配一维数组输入(推荐,保持效率)
直接调整函数的取值逻辑,从一维数组中提取四个坐标值,同时保留raw=True以维持计算效率:
import pandas as pd import numpy as np def haversine_distance(arr): # 一维数组顺序:lat1, lon1, lat2, lon2 lat1, lon1, lat2, lon2 = arr # 转换为弧度 lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2]) # Haversine公式计算 dlon = lon2 - lon1 dlat = lat2 - lat1 a = np.sin(dlat / 2.0) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2.0) ** 2 c = 2 * np.arcsin(np.sqrt(a)) km = 6371 * c return km # 示例DataFrame df = pd.DataFrame({'Latitude': [40.7128, 37.7749, 34.0522], 'Longitude': [-74.0060, -122.4194, -118.2437]}) # 计算距离并填充第一个值为0 df['DISTANCE'] = df[['Latitude', 'Longitude']].rolling(window=2).apply(haversine_distance, raw=True) df['DISTANCE'] = df['DISTANCE'].fillna(0) print(df.round(4))
运行结果与预期一致:
Latitude Longitude DISTANCE 0 40.7128 -74.0060 0.0000 1 37.7749 -122.4194 4129.0861 2 34.0522 -118.2437 559.1205
解决方案2:移除raw=True,调整函数适配二维输入
如果不想修改函数核心逻辑,可以去掉raw=True,此时传入函数的是2行2列的DataFrame切片,调整索引方式即可:
def haversine_distance(df_slice): lat1, lat2 = df_slice.iloc[0,0], df_slice.iloc[1,0] lon1, lon2 = df_slice.iloc[0,1], df_slice.iloc[1,1] # 后续弧度转换和公式计算与原函数一致 lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2]) dlon = lon2 - lon1 dlat = lat2 - lat1 a = np.sin(dlat / 2.0) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2.0) ** 2 c = 2 * np.arcsin(np.sqrt(a)) km = 6371 * c return km # 计算时移除raw=True df['DISTANCE'] = df[['Latitude', 'Longitude']].rolling(window=2).apply(haversine_distance) df['DISTANCE'] = df['DISTANCE'].fillna(0)
注意事项
rolling(window=2)的第一个结果是NaN,因为第一个窗口只有1行数据,所以需要用fillna(0)填充为预期的初始值。- 方案1的效率更高,因为
raw=True会直接传递numpy数组,避免了DataFrame切片的额外开销,适合处理大规模数据集。
内容的提问来源于stack exchange,提问作者madhav Venkatesh
相关产品推荐
相关产品推荐

