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

基于多规则的两个Pandas DataFrame匹配方案咨询

Pandas DataFrame按优先级规则实现唯一匹配的高效方案

核心思路

不用循环,靠分层匹配+标记已用记录的方式实现:按匹配优先级从高到低依次匹配,每完成一级匹配就从数据库中移除已被使用的记录,确保每条数据库记录仅被匹配一次。

实现步骤与代码

假设我们有两个结构一致的DataFrame:df_persons(待匹配数据集)和df_database(候选匹配数据集),列均为cu_id, sex, eye_colour, favourite_sport, cash_on_account。

1. 预处理:准备临时数据库与匹配状态跟踪

import pandas as pd

# 复制数据库到临时表,避免修改原数据
temp_db = df_database.copy()
# 初始化匹配结果表
matched_results = pd.DataFrame(columns=df_persons.columns.tolist() + ['matched_cu_id'])

# 标记未匹配的人员(初始为全部)
unmatched_persons = df_persons.copy()

2. 按优先级依次匹配

优先级1:匹配sex、eye_colour、favourite_sport全一致的记录
# 合并匹配
level1_match = pd.merge(
    unmatched_persons, temp_db,
    on=['sex', 'eye_colour', 'favourite_sport'],
    suffixes=('_person', '_db')
)
# 对每个人员取第一条匹配(保证唯一),并提取关键列
level1_match = level1_match.groupby('cu_id_person').first().reset_index()
level1_match = level1_match[['cu_id_person', 'cu_id_db']].rename(columns={'cu_id_person': 'cu_id', 'cu_id_db': 'matched_cu_id'})

# 更新匹配结果、未匹配人员和临时数据库
matched_results = pd.concat([matched_results, level1_match], ignore_index=True)
unmatched_persons = unmatched_persons[~unmatched_persons['cu_id'].isin(level1_match['cu_id'])]
temp_db = temp_db[~temp_db['cu_id'].isin(level1_match['matched_cu_id'])]
优先级2:匹配sex、eye_colour一致的记录
if not unmatched_persons.empty and not temp_db.empty:
    level2_match = pd.merge(
        unmatched_persons, temp_db,
        on=['sex', 'eye_colour'],
        suffixes=('_person', '_db')
    )
    level2_match = level2_match.groupby('cu_id_person').first().reset_index()
    level2_match = level2_match[['cu_id_person', 'cu_id_db']].rename(columns={'cu_id_person': 'cu_id', 'cu_id_db': 'matched_cu_id'})

    matched_results = pd.concat([matched_results, level2_match], ignore_index=True)
    unmatched_persons = unmatched_persons[~unmatched_persons['cu_id'].isin(level2_match['cu_id'])]
    temp_db = temp_db[~temp_db['cu_id'].isin(level2_match['matched_cu_id'])]
优先级3:仅匹配sex一致的记录
if not unmatched_persons.empty and not temp_db.empty:
    level3_match = pd.merge(
        unmatched_persons, temp_db,
        on=['sex'],
        suffixes=('_person', '_db')
    )
    level3_match = level3_match.groupby('cu_id_person').first().reset_index()
    level3_match = level3_match[['cu_id_person', 'cu_id_db']].rename(columns={'cu_id_person': 'cu_id', 'cu_id_db': 'matched_cu_id'})

    matched_results = pd.concat([matched_results, level3_match], ignore_index=True)
    unmatched_persons = unmatched_persons[~unmatched_persons['cu_id'].isin(level3_match['cu_id'])]
    temp_db = temp_db[~temp_db['cu_id'].isin(level3_match['matched_cu_id'])]
优先级4:匹配cash_on_account最高的记录
if not unmatched_persons.empty and not temp_db.empty:
    # 先给数据库按cash_on_account降序排序,确保优先取金额最高的
    temp_db_sorted = temp_db.sort_values('cash_on_account', ascending=False).reset_index(drop=True)
    # 给未匹配人员和排序后的数据库按索引匹配(一一对应,直到其中一方耗尽)
    match_count = min(len(unmatched_persons), len(temp_db_sorted))
    level4_match = pd.DataFrame({
        'cu_id': unmatched_persons.iloc[:match_count]['cu_id'].values,
        'matched_cu_id': temp_db_sorted.iloc[:match_count]['cu_id'].values
    })
    # 处理剩余未匹配项
    if len(unmatched_persons) > match_count:
        unmatched_persons = unmatched_persons.iloc[match_count:]
    temp_db = temp_db_sorted.iloc[match_count:]

    matched_results = pd.concat([matched_results, level4_match], ignore_index=True)

3. 合并最终结果

最后把匹配结果和原人员表合并,得到完整的匹配数据:

final_result = pd.merge(df_persons, matched_results, on='cu_id', how='left')

关键说明

  • 每一级匹配后都会从临时数据库中移除已使用的记录,严格保证唯一匹配;
  • 所有操作均基于Pandas的向量式运算,避免了循环带来的性能问题;
  • 优先级4中采用按金额降序后按索引匹配的方式,高效实现“取最高金额”的需求,同时保证记录唯一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:09:22