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

如何在pandas merge_asof中保留仅存在于右表的用户?

问题描述

现有如下Pandas数据:

df1

user_id create_at
0   1   2023-01-01
1   1   2023-01-02
2   2   2023-01-01
3   2   2023-01-03
4   2   2023-01-05

df2

user_id withdrawal_request_date
0   1   2023-01-03
1   2   2023-01-02
2   3   2023-01-01

我尝试执行merge_asof操作,代码及结果如下:

pd.merge_asof(df1.sort_values('create_at'), 
              df2.sort_values('withdrawal_request_date'), 
              by = 'user_id', 
              left_on = 'create_at', 
              right_on = 'withdrawal_request_date', 
              direction = 'forward')

执行结果:

user_id create_at   withdrawal_request_date
0   1   2023-01-01  2023-01-03
1   2   2023-01-01  2023-01-02
2   1   2023-01-02  2023-01-03
3   2   2023-01-03  NaT
4   2   2023-01-05  NaT

但结果丢失了仅存在于df2中的user_id=3的用户,期望输出如下:

user_id create_at   withdrawal_request_date
0   1   2023-01-01  2023-01-03
1   2   2023-01-01  2023-01-02
2   1   2023-01-02  2023-01-03
3   2   2023-01-03  NaT
4   2   2023-01-05  NaT
5   3   NaT         2023-01-01

注意:数据集规模极大,包含数千用户及大量行为数据,因此无法使用outer joins这类方法。

数据定义代码:

import pandas as pd

df1 = pd.DataFrame({
    'user_id': [1, 1, 2, 2, 2],
    'create_at': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-01', '2023-01-03', '2023-01-05'])
})

df2 = pd.DataFrame({
    'user_id': [1, 2, 3],
    'withdrawal_request_date': pd.to_datetime(['2023-01-03', '2023-01-02', '2023-01-01'])
})
解决方案

可以通过拆分处理+高效拼接的方式实现,避免outer join带来的性能问题:

  1. 先执行原merge_asof操作得到基础结果
  2. 筛选出df2中仅有的用户数据(即user_id不在df1中的记录)
  3. 给这部分数据补充create_at列,值设为NaT
  4. 将基础结果和补充数据高效拼接

具体代码如下:

# 1. 执行原merge_asof操作
df_merge = pd.merge_asof(
    df1.sort_values('create_at'), 
    df2.sort_values('withdrawal_request_date'), 
    by='user_id', 
    left_on='create_at', 
    right_on='withdrawal_request_date', 
    direction='forward'
)

# 2. 筛选df2独有的用户记录
df2_only = df2[~df2['user_id'].isin(df1['user_id'].unique())].copy()

# 3. 补充create_at列
df2_only['create_at'] = pd.NaT

# 4. 调整列顺序,和df_merge保持一致,然后拼接
df2_only = df2_only[['user_id', 'create_at', 'withdrawal_request_date']]
final_df = pd.concat([df_merge, df2_only], ignore_index=True)

print(final_df)

方案优势

  • 筛选df2独有用户时,isin配合unique()是向量化操作,效率远高于循环或全表比对
  • pd.concat是内存高效的拼接方式,不会产生额外的笛卡尔积,完全适配大规模数据集

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 07:49:52