如何基于条件合并两个DataFrame并匹配对应id
实现方法
先构造示例数据方便复现:
import pandas as pd # 构造df1 df1 = pd.DataFrame({ 'name': ['name_1', 'name_2', 'name_3', 'name_1'], 'year': [2018, 2017, 2021, 2022] }) # 构造df2 df2 = pd.DataFrame({ 'name': ['name_1', 'name_2', 'name_1'], 'start': [2017, 2017, 2022], 'end': [2021, 2022, 2023], 'id': [1, 2, 3] })
方法一:先合并再过滤(适合小数据集)
先通过name字段做全连接,再筛选year落在[start, end)区间的记录,最后保留目标列:
# 按name合并两个DataFrame merged = pd.merge(df1, df2, on='name', how='left') # 过滤符合年份区间的记录 result = merged[(merged['year'] >= merged['start']) & (merged['year'] < merged['end'])] # 保留原df1的列和匹配到的id result = result[['name', 'year', 'id']]
执行后结果:
| name | year | id |
|---|---|---|
| name_1 | 2018 | 1 |
| name_2 | 2017 | 2 |
| name_1 | 2022 | 3 |
注:无匹配区间的记录会被过滤,若需保留所有df1行并将无匹配的id设为NaN,可后续和原df1做左连接。
方法二:用merge_asof高效匹配(适合大数据集)
Pandas的merge_asof专为有序键的区间左连接设计,不会产生笛卡尔积,性能远优于全连接后过滤:
# 对两个DataFrame按name和年份类字段排序(merge_asof要求键有序) df1_sorted = df1.sort_values(['name', 'year']) df2_sorted = df2.sort_values(['name', 'start']) # 执行区间匹配 result = pd.merge_asof( df1_sorted, df2_sorted, by='name', # 按name分组匹配 left_on='year', right_on='start', direction='backward', # 匹配小于等于year的最大start值 allow_exact_matches=True ) # 过滤掉year >= end的记录(满足year < end的条件) result = result[result['year'] < result['end']] # 恢复原df1的行顺序并保留目标列 result = result[['name', 'year', 'id']].sort_index()
若需保留df1所有行(无匹配时id为NaN),可执行:
final_result = df1.merge(result[['name', 'year', 'id']], on=['name', 'year'], how='left')
最终结果:
| name | year | id |
|---|---|---|
| name_1 | 2018 | 1 |
| name_2 | 2017 | 2 |
| name_3 | 2021 | NaN |
| name_1 | 2022 | 3 |
内容的提问来源于stack exchange,提问作者Aniss Chohra
相关产品推荐
相关产品推荐

