pandas合并DataFrame时能否限制指定数据框行的最大使用次数
实现思路
核心是先保留dfA的原始顺序和dfB的行顺序,通过同type关联得到所有候选匹配,再按优先级筛选结果,保证每个dfB行的使用次数不超过其n值:
- 给dfA加原始索引列,避免排序打乱原有顺序;给dfB加自身行索引,唯一标识每一行
- 按
type关联两个表,得到同type下的所有匹配组合 - 按dfA原始顺序、dfB行顺序排序,保证匹配优先级符合要求
- 控制每个dfB行的使用次数不超过
n,同时每个dfA行只保留第一个匹配到的结果 - 左连接回原始dfA,无匹配的
name字段填充为NO MATCH
代码实现
import pandas as pd def match_df(dfA, dfB): # 添加索引保留原有顺序 dfA = dfA.reset_index(names='orig_idx') dfB = dfB.reset_index(names='b_idx') # 按type关联所有同类型候选 merged = dfA[['orig_idx', 'type']].merge(dfB, on='type', how='left') # 按优先级排序:先按dfA原始顺序,再按dfB行顺序 merged = merged.sort_values(by=['orig_idx', 'b_idx'], ignore_index=True) # 控制每个dfB行的使用次数不超过对应n值 merged['b_used_cnt'] = merged.groupby('b_idx').cumcount() + 1 merged = merged[merged['b_used_cnt'] <= merged['n']] # 每个dfA行只保留第一个匹配到的结果 merged = merged.drop_duplicates(subset=['orig_idx'], keep='first') # 左连接回原dfA,填充无匹配的值 res = dfA.merge(merged[['orig_idx', 'name']], on='orig_idx', how='left') res['name'] = res['name'].fillna('NO MATCH') # 按原始顺序返回结果,去掉辅助列 return res.sort_values(by='orig_idx')[['type', 'name']].reset_index(drop=True)
测试验证
第一个示例测试
# 构造第一个示例数据 dfA = pd.DataFrame({'type': ['A', 'B', 'A', 'B', 'A']}) dfB = pd.DataFrame({ 'type': ['A', 'B', 'A', 'B'], 'name': ['123', '123', '456', '789'], 'n': [1, 1, 1, 1] }) print(match_df(dfA, dfB))
第二个示例测试
# 调整dfA顺序为第二个示例的输入 dfA = pd.DataFrame({'type': ['B', 'A', 'B', 'A', 'B']}) print(match_df(dfA, dfB))
两次运行结果完全符合需求规则,dfB行使用次数不超过n值,无匹配时返回NO MATCH。
内容的提问来源于stack exchange,提问作者Jan T.
相关产品推荐
相关产品推荐

