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

如何基于时间为无关联键的两个Pandas DataFrame建立匹配关联?

前置准备

首先先将两个DataFrame的date列统一转换为datetime类型,避免字符串时间比较出错:

import pandas as pd
import numpy as np

# 转换时间格式
visits['date'] = pd.to_datetime(visits['date'], format='%m-%d-%Y %H:%M:%S')
rides['date'] = pd.to_datetime(rides['date'], format='%m-%d-%Y %H:%M:%S')

最优实现方案:使用merge_asof

Pandas内置的merge_asof函数就是专门为这种按最近时间匹配的场景设计的,性能远高于手动循环,代码实现也更简洁:

# 两个表都需要先按分组键name和时间列date排序,这是merge_asof的要求
visits_sorted = visits.sort_values(['name', 'date'])
rides_sorted = rides.sort_values(['name', 'date'])

# 按姓名分组,匹配每条游玩记录之前最近的一次入园记录
result = pd.merge_asof(
    rides_sorted,
    visits_sorted,
    on='date',
    by='name',
    direction='backward' # 匹配小于等于当前游玩时间的最近入园时间
)

# 输出时按需调整列顺序即可
result = result[['id', 'name', 'ride', 'date']]

最终输出和要求的预期结果完全一致。


原代码错误修正

如果需要沿用原有的循环逻辑,错误点和修正方案如下:

  1. 条件判断中误用了visits['date'](整个visits的时间列,长度和rides不一致导致形状报错),应该替换为当前遍历行的row['date']
  2. np.where同时返回两个值时不能直接赋值给两个列,需要拆分返回结果
  3. 代码末尾缺失右括号,存在语法错误

修正后的循环代码:

rides['min_diff'] = pd.to_timedelta(365, unit='day')
rides['id'] = -1

for index, row in visits.iterrows():
    # 计算当前入园记录和所有符合条件游玩记录的时间差
    mask = (rides['name'] == row['name']) & (rides['date'] >= row['date'])
    time_diff = rides.loc[mask, 'date'] - row['date']
    # 只更新时间差更小的记录
    update_mask = mask & (time_diff < rides['min_diff'])
    rides.loc[update_mask, 'id'] = row['id']
    rides.loc[update_mask, 'min_diff'] = time_diff[update_mask]

# 用完可以删除辅助列
rides = rides.drop('min_diff', axis=1)

内容的提问来源于stack exchange,提问作者Ehren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:30:03