Python3 Pandas:合并含重复键的DataFrame,避免n²匹配仅保留n行
解决重复键DataFrame的一对一合并问题
你遇到的场景非常典型:当两个DataFrame的连接键存在重复(比如同一本书多次借还),直接用内连接会生成所有可能的组合(n²行),但我们需要的是同键下第n次记录的一对一匹配(n行)。下面用图书馆借还书的场景给你具体解决方案:
核心思路
给每个书籍(唯一键)的入库/出库记录按时间顺序添加「序列编号」,然后用「书籍ID+序列编号」作为连接键进行合并,这样就能保证同一本书的第1次入库对应第1次出库,第2次对应第2次,以此类推。
具体步骤(以Pandas为例)
1. 准备示例数据
先模拟你的入库(df1)和出库(df2)数据集:
import pandas as pd # 入库记录:book_id为书籍唯一标识,in_date是入库时间 df1 = pd.DataFrame({ 'book_id': [1, 1, 2, 3], 'in_date': ['2023-01-01', '2023-02-01', '2023-01-15', '2023-03-01'], 'in_operator': ['Alice', 'Bob', 'Alice', 'Charlie'] }) # 出库记录:out_date是出库时间 df2 = pd.DataFrame({ 'book_id': [1, 1, 2, 3], 'out_date': ['2023-01-10', '2023-02-10', '2023-01-20', '2023-03-05'], 'out_operator': ['Dave', 'Eve', 'Dave', 'Frank'] })
2. 给分组内的记录添加序列编号
首先要按书籍ID+时间排序(保证借还顺序正确),然后给每个书籍分组内的行分配序号:
# 处理入库记录:按book_id和in_date排序,添加sequence列 df1_sorted = df1.sort_values(['book_id', 'in_date']).reset_index(drop=True) df1_sorted['sequence'] = df1_sorted.groupby('book_id').cumcount() + 1 # 1-based序号 # 处理出库记录:同理按book_id和out_date排序,添加sequence列 df2_sorted = df2.sort_values(['book_id', 'out_date']).reset_index(drop=True) df2_sorted['sequence'] = df2_sorted.groupby('book_id').cumcount() + 1
3. 用复合键进行合并
现在用book_id和sequence作为连接键做内连接,就能得到我们需要的n行结果:
merged_df = pd.merge(df1_sorted, df2_sorted, on=['book_id', 'sequence'], how='inner') print(merged_df)
输出结果会是:
book_id in_date in_operator sequence out_date out_operator 0 1 2023-01-01 Alice 1 2023-01-10 Dave 1 1 2023-02-01 Bob 2 2023-02-10 Eve 2 2 2023-01-15 Alice 1 2023-01-20 Dave 3 3 2023-03-01 Charlie 1 2023-03-05 Frank
边界情况处理
- 如果某本书的入库次数和出库次数不一致(比如只入库没出库,或反之),内连接会自动过滤掉不匹配的行;如果需要保留所有记录,可以用
how='outer',然后用fillna()处理缺失值。 - 如果时间字段有缺失,需要先清理数据,或者用其他排序依据(比如记录创建时间)保证序列的正确性。
内容的提问来源于stack exchange,提问作者Samadin
相关产品推荐
相关产品推荐

