Python中按日期时间与最近几何距离合并两个DataFrame的方法
问题修复及最优实现方案
NaN值产生的核心原因
- 时间匹配阶段:使用
pd.merge_asof前未对两个表的时间列做升序排序,导致匹配错位漏匹配;或merge_asof的tolerance参数未与180分钟的误差要求对齐,边界时间被过滤 - 空间匹配阶段:使用WGS84等地理坐标系直接计算距离,得到的单位为度而非米,若设置了不合理的距离阈值会把有效匹配过滤;或仅按时间分组留存唯一最近Point,忽略了同时间窗下不同LineString对应的最近Point存在差异,导致多数LineString匹配不到留存的Point
- 合理无匹配:部分road行的时间确实不存在180分钟误差范围内的weather记录,该类NaN属于正常结果无需修复
原有逻辑修复方案
- 对weather、road表的时间列统一转为
datetime64格式并校准时区后,做升序排序 - 调整
merge_asof参数,显式设置tolerance=pd.Timedelta(minutes=180)、direction='nearest' - 放弃全局按时间去重Point的逻辑,改为对每个road行匹配对应时间窗内的所有Point,单独计算最近点
更高效的完整实现方案
基于geopandas的sjoin_nearest实现时间+空间的双层匹配,代码示例如下:
import pandas as pd import geopandas as gpd from geopandas.tools import sjoin_nearest # 前置数据校准 # 统一时间格式与时区 weather['time'] = pd.to_datetime(weather['time'], utc=True) road['time'] = pd.to_datetime(road['time'], utc=True) # 统一转为投影坐标系(下方epsg替换为研究区域对应的UTM坐标系,保证距离单位为米) weather = gpd.GeoDataFrame(weather, geometry='geometry').to_crs(epsg=32650) road = gpd.GeoDataFrame(road, geometry='geometry').to_crs(epsg=32650) # 第一步:时间粗匹配,筛选所有时间差≤180分钟的配对 weather = weather.sort_values('time').reset_index(drop=True) road = road.sort_values('time').reset_index(drop=True) # 为weather每个时间点生成180分钟误差的时间区间 weather['time_interval'] = pd.IntervalIndex.from_arrays( weather['time'] - pd.Timedelta(minutes=180), weather['time'] + pd.Timedelta(minutes=180), closed='both' ) # 匹配road时间对应的weather索引 road['weather_time_idx'] = road['time'].apply( lambda x: weather[weather['time_interval'].apply(lambda y: x in y)].index.tolist() ) # 拆分多匹配行,过滤无时间匹配的行 road_exploded = road.explode('weather_time_idx').dropna(subset=['weather_time_idx']).reset_index(drop=True) weather_matched = weather.loc[road_exploded['weather_time_idx']].reset_index(drop=True) # 第二步:空间最近匹配,每个road行匹配对应时间窗内的最近Point merged = sjoin_nearest( road_exploded, weather_matched, how='left', lsuffix='_road', rsuffix='_weather', distance_col='geo_distance' ) # 补回无时间匹配的原始road行,得到最终结果 final_res = pd.concat([merged, road[road['weather_time_idx'].apply(len) == 0]], ignore_index=True)
剩余NaN排查方法
- 提取结果中为NaN的行,核查其时间在weather表中是否存在180分钟内的对应记录,无记录则为合理无匹配
- 若存在时间匹配记录,核查两个表的坐标系是否一致、是否为投影坐标系,排除空间计算错误导致的匹配失败
内容的提问来源于stack exchange,提问作者Ümran
相关产品推荐
相关产品推荐

