You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中按日期时间与最近几何距离合并两个DataFrame的方法

问题修复及最优实现方案

NaN值产生的核心原因

  • 时间匹配阶段:使用pd.merge_asof前未对两个表的时间列做升序排序,导致匹配错位漏匹配;或merge_asof的tolerance参数未与180分钟的误差要求对齐,边界时间被过滤
  • 空间匹配阶段:使用WGS84等地理坐标系直接计算距离,得到的单位为度而非米,若设置了不合理的距离阈值会把有效匹配过滤;或仅按时间分组留存唯一最近Point,忽略了同时间窗下不同LineString对应的最近Point存在差异,导致多数LineString匹配不到留存的Point
  • 合理无匹配:部分road行的时间确实不存在180分钟误差范围内的weather记录,该类NaN属于正常结果无需修复

原有逻辑修复方案

  1. 对weather、road表的时间列统一转为datetime64格式并校准时区后,做升序排序
  2. 调整merge_asof参数,显式设置tolerance=pd.Timedelta(minutes=180)、direction='nearest'
  3. 放弃全局按时间去重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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:48:04