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

如何用Pandas基于多列匹配替换project_id且保持数据集结构不变?

解决方案

问题根源

  1. 列名不匹配:数据集A的列是deliv,但代码中使用了delivery,导致匹配逻辑失效。
  2. 多对多匹配:B中存在同一组匹配键(Tags, ID, qtr, TYPE, msc)对应多个Project Name的情况(如2022/BR/Q2 2022/dd/d对应两个项目名),左连接时生成笛卡尔积,导致行数激增。

正确实现代码(完全匹配期望结果)

从期望结果可看出,A中同一匹配键的不同行对应B中NUM列的不同值(如A中dd1对应B的01,dd2对应02),因此需补充NUM作为匹配条件:

import pandas as pd

# 1. 从A的project_id中提取NUM并补零为两位(匹配B的NUM格式)
df_A['NUM'] = df_A['project_id'].str.extract(r'(\d+)').str.zfill(2)

# 2. 准备B的映射表,保留需要的匹配列
df_B_mapping = df_B[['Project Name', 'Tags', 'ID', 'qtr', 'TYPE', 'msc', 'NUM']]

# 3. 执行左连接,使用完整匹配键(含NUM),避免多对多膨胀
df_merged = pd.merge(
    df_A,
    df_B_mapping,
    how='left',
    left_on=['Year', 'ID', 'deliv', 'type', 'vendor', 'NUM'],
    right_on=['Tags', 'ID', 'qtr', 'TYPE', 'msc', 'NUM']
)

# 4. 替换project_id:有匹配则用B的Project Name,无匹配则保留原A的值
df_A['project_id'] = df_merged['Project Name'].combine_first(df_A['project_id'])

# 5. 移除临时添加的NUM列,恢复原A的列结构
df_A.drop('NUM', axis=1, inplace=True)

# 输出结果
print(df_A)

简化方案(若无需区分NUM)

若允许同一匹配键仅取B中第一个出现的Project Name,可先对B去重再连接:

# 对B按匹配键去重,保留第一个项目名
df_B_unique = df_B.drop_duplicates(subset=['Tags', 'ID', 'qtr', 'TYPE', 'msc'], keep='first')

# 执行左连接,修正列名错误
df_merged = pd.merge(
    df_A,
    df_B_unique[['Project Name', 'Tags', 'ID', 'qtr', 'TYPE', 'msc']],
    how='left',
    left_on=['Year', 'ID', 'deliv', 'type', 'vendor'],
    right_on=['Tags', 'ID', 'qtr', 'TYPE', 'msc']
)

# 替换project_id
df_A['project_id'] = df_merged['Project Name'].combine_first(df_A['project_id'])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:25:55