如何基于ID和24小时内的时间模糊合并两个Pandas DataFrame
基于ID匹配+24小时内时间差合并DataFrame的优雅实现
问题背景
我有两个DataFrame:dfA和dfB,需要在ID完全相同且日期时间相差不超过24小时的条件下合并。用常规pd.merge按id和date精确匹配时,第三条数据因时间不完全一致被错误排除,需要调整实现逻辑。
初始尝试代码
import numpy as np import pandas as pd import datetime dfA = pd.DataFrame({ 'id': [1,2,3], 'date': [datetime.datetime(2000, 1, 1, 22, 52), datetime.datetime(2000, 1, 2, 22, 53), datetime.datetime(2000, 1, 3, 22, 53)], 'value1': ['N','N','Y'] }) dfB = pd.DataFrame({ 'id': [1,2,3], 'date': [datetime.datetime(2000, 1, 1, 22, 52), datetime.datetime(2000, 1, 2, 22, 53), datetime.datetime(2000, 1, 4, 10, 11)], 'value2': ['Y','Y','N'] }) print(dfA) print(dfB) print(pd.merge(dfA, dfB, on=['id','date']))
循环实现的解决方案(不够优雅)
我用嵌套循环实现了需求,但效率和简洁性都不足:
dfA = dfA.add_suffix('_A') dfB = dfB.add_suffix('_B') newData = [] for indexA, rowA in dfA.iterrows(): for indexB, rowB in dfB.iterrows(): if rowA['id_A'] == rowB['id_B']: if 86401 > abs((rowB['date_B']-rowA['date_A']).total_seconds()): newData.append({**rowA.to_dict(), **rowB.to_dict()}) mergedDf = pd.DataFrame(newData)
优雅解决方案
可以先按id做笛卡尔积合并,再过滤时间差符合条件的行,代码简洁且性能更优:
import pandas as pd import datetime # 初始数据 dfA = pd.DataFrame({ 'id': [1,2,3], 'date': [datetime.datetime(2000, 1, 1, 22, 52), datetime.datetime(2000, 1, 2, 22, 53), datetime.datetime(2000, 1, 3, 22, 53)], 'value1': ['N','N','Y'] }) dfB = pd.DataFrame({ 'id': [1,2,3], 'date': [datetime.datetime(2000, 1, 1, 22, 52), datetime.datetime(2000, 1, 2, 22, 53), datetime.datetime(2000, 1, 4, 10, 11)], 'value2': ['Y','Y','N'] }) # 步骤1:按id合并,得到所有同ID的行组合 merged = pd.merge(dfA, dfB, on='id', suffixes=('_A', '_B')) # 步骤2:计算时间差并过滤24小时内的行 time_diff = abs(merged['date_A'] - merged['date_B']) result = merged[time_diff <= pd.Timedelta(days=1)] print(result)
核心说明
- 先通过
pd.merge(dfA, dfB, on='id')获取所有同ID的行组合,避免嵌套循环的低效遍历 - 用
pd.Timedelta(days=1)直接表示24小时,比手动计算秒数更直观易读 - 基于时间差列做过滤,逻辑清晰,数据量大时性能远优于循环实现
内容的提问来源于stack exchange,提问作者user8793002
相关产品推荐
相关产品推荐

