基于空间位置(lon、lat)与datetime匹配近邻,为DataFrame补充温度数据
时空近邻匹配:为Dataset 1新增温度列的实现方案
需求概述
你需要基于优先空间近邻、再时间近邻的规则,从Dataset 2中为Dataset 1的每个采样点匹配对应的温度值:
- Dataset 1:仅包含采样点的
datetime、longitude、latitude - Dataset 2:包含大范围时空的温度数据,需筛选出与Dataset 1点最匹配的记录
解决方案(Python实现)
针对大型数据集,我们采用空间索引加速近邻查询+时间差筛选的组合方案,兼顾效率和准确性。
1. 数据预处理
首先确保两个数据集的时间格式为datetime,经纬度为数值类型:
import pandas as pd from scipy.spatial import KDTree import numpy as np # 加载数据集(替换为你的实际数据路径) df1 = pd.read_csv("dataset1.csv", parse_dates=["datetime"]) df2 = pd.read_csv("dataset2.csv", parse_dates=["datetime"]) # 确保经纬度是数值型 df1[["longitude", "latitude"]] = df1[["longitude", "latitude"]].astype(float) df2[["longitude", "latitude"]] = df2[["longitude", "latitude"]].astype(float)
2. 构建空间索引(KDTree)
用KDTree对Dataset 2的经纬度构建空间索引,大幅提升大型数据集的近邻查询速度:
# 提取Dataset 2的经纬度坐标,转为数组格式 coords2 = df2[["longitude", "latitude"]].values kdtree = KDTree(coords2)
3. 时空近邻匹配逻辑
对Dataset 1的每个点,先查询空间最近的N个候选点(N可根据数据密度调整,这里设为5),再在候选点中筛选时间最近的记录,提取温度值:
def match_temp(row): # 当前点的经纬度和时间 lon, lat = row["longitude"], row["latitude"] dt = row["datetime"] # 1. 查询空间最近的5个候选点(返回距离和索引) distances, indices = kdtree.query([[lon, lat]], k=5) candidates = df2.iloc[indices[0]] # 2. 计算候选点与当前点的时间差绝对值 candidates["time_diff"] = abs(candidates["datetime"] - dt) # 3. 找到时间差最小的候选点,返回对应的温度 closest_candidate = candidates.sort_values("time_diff").iloc[0] return closest_candidate["temp"] # 为Dataset 1新增temp列 df1["temp"] = df1.apply(match_temp, axis=1)
4. 结果验证
运行后你将得到符合预期的结果:
datetime longitude latitude temp 0 2022-08-10 03:26:08 147.8521 -20.2443 21.49 1 2020-10-02 16:12:52 152.3652 -23.1234 20.80
优化说明
- 如果Dataset 2数据量极大,可调整
k值(候选点数量)平衡速度和准确性; - 若空间精度要求高,可改用Haversine公式计算实际球面距离(替代KDTree的欧氏距离),适合经纬度地理数据:
此时需遍历计算距离,但可通过分批处理优化效率。def haversine(lon1, lat1, lon2, lat2): lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2]) dlon = lon2 - lon1 dlat = lat2 - lat1 a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2 c = 2 * np.arcsin(np.sqrt(a)) r = 6371 # 地球半径(公里) return c * r
内容的提问来源于stack exchange,提问作者Boogaloo
相关产品推荐
相关产品推荐

