如何基于0.005米距离聚合Pandas中经纬度关联的Val列均值
解决按0.005米地理范围迭代聚合的问题
你提到的需求没办法直接用pandas.Grouper实现,因为它是基于固定分组规则,而你的需求是动态迭代分组——以当前未处理的第一个点为基准,圈定0.005米范围的所有点聚合,再跳到范围外的下一个点重复操作。下面是具体的实现步骤和代码:
步骤说明
- 首先实现经纬度坐标的距离计算(这里用Haversine公式,适合短距离的精确计算);
- 迭代遍历数据:每次取当前未处理的第一个点作为基准,筛选出所有距离它≤0.005米的记录;
- 对筛选出的记录计算
Val的均值、记录数,用基准点的坐标作为分组标识(也可以选择用该组的平均坐标,按需调整); - 跳过已处理的记录,重复直到所有数据都被聚合。
完整代码实现
import pandas as pd import numpy as np # 定义Haversine距离计算函数(单位:米) 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)) return R * c # 构造你的示例DataFrame data = { 'Time': ['19:24:50.925', '19:24:51.022', '19:24:51.118', '19:24:51.215', '19:24:51.312', '19:24:51.409', '19:24:51.506', '19:24:51.603', '19:24:51.699', '19:24:51.796', '19:24:51.892', '19:24:51.990', '19:24:52.087', '19:24:52.183', '19:24:52.281', '19:24:52.378', '19:24:52.474', '19:24:52.571', '19:24:52.668'], 'Lat': [35.61068333, 35.61068333, 35.61068333, 35.61068394, 35.61068455, 35.61068515, 35.61068576, 35.61068636, 35.61068697, 35.61068758, 35.61068818, 35.61068879, 35.61068939, 35.61069042, 35.61069083, 35.61069125, 35.61069222, 35.61069278, 35.61069333], 'Long': [139.6304283]*19, 'Val': [-54.6, -52.9, -52.6, -52.2, -49.3, -52.1, -52.2, -51.3, -51.8, -52.6, -53.5, -51.8, -54.1, -51.8, -53.5, -55.6, -53.2, -50.8, -54] } df = pd.DataFrame(data) # 初始化结果列表和当前起始索引 result = [] current_idx = 0 total_rows = len(df) while current_idx < total_rows: # 取当前基准点的坐标 base_lat = df.iloc[current_idx]['Lat'] base_lon = df.iloc[current_idx]['Long'] # 计算所有未处理行到基准点的距离 distances = haversine(base_lat, base_lon, df['Lat'][current_idx:], df['Long'][current_idx:]) # 筛选距离≤0.005米的行的索引(相对于未处理的子DataFrame) mask = distances <= 0.005 group_indices = mask[mask].index # 获取对应的原DataFrame的行范围 start = current_idx end = current_idx + len(group_indices) # 提取分组数据 group_df = df.iloc[start:end] # 计算聚合值:用基准点的坐标,Val均值,记录数 agg_result = { 'Lat': base_lat, 'Long': base_lon, 'Val_mean': group_df['Val'].mean(), 'Count_of_records': len(group_df) } result.append(agg_result) # 更新当前起始索引到分组的下一行 current_idx = end # 转换为结果DataFrame result_df = pd.DataFrame(result) print(result_df)
代码细节说明
- Haversine函数:精确计算经纬度两点间的球面距离,单位转换为米,完全匹配你0.005米的范围要求;
- 迭代逻辑:严格遵循你描述的“从第一个位置为基准,范围外的下一个位置重复”的规则,不会出现重复或遗漏的记录;
- 聚合自定义:如果需要用分组的平均坐标代替基准点坐标,只需要把
base_lat换成group_df['Lat'].mean(),base_lon同理即可。
性能提示
如果你的数据量非常大,这种迭代方式效率可能稍低,此时可以考虑引入空间索引库(比如rtree)来加速距离筛选;但对于中小规模的数据,上面的代码足够高效且易读。
内容的提问来源于stack exchange,提问作者user3206440
相关产品推荐
相关产品推荐

