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

基于Python实现Vlookup匹配及不匹配原因排查的代码优化问询

问题分析与代码优化方案

原代码核心问题

  1. 拼接列引用错误:代码中出现df2_of01['Date']、df2_Name['Date']这类笔误,引用了不存在的DataFrame,导致拼接结果完全错误。
  2. 字段匹配逻辑混乱:
    • Date匹配判断时,用df2_B.loc[df2_B['B_Concate'] == row['A_Concate'], 'Date']筛选,而整体不匹配时该结果为空,会错误返回Not match date。
    • Quantity匹配逻辑存在未定义变量(Match part?、SUGGESTED QTY),且未结合Name/Date的关联关系判断,忽略了一对多数据场景。
  3. 数据格式未统一:Date的字符串格式、Quantity的类型转换不一致,可能导致本该匹配的记录因格式差异被误判为不匹配。

优化后的完整代码

import pandas as pd
import numpy as np

# 1. 复制数据并统一字段格式,修正拼接逻辑
df2_A = df1_A.copy()
df2_B = df1_B.copy()

# 统一处理Date格式(避免datetime转字符串时的格式差异)
df2_A['Date_str'] = pd.to_datetime(df2_A['Date']).dt.strftime('%Y-%m-%d')
df2_B['Date_str'] = pd.to_datetime(df2_B['Date']).dt.strftime('%Y-%m-%d')

# 统一Quantity类型(转int后再转字符串,避免float类型的.0后缀)
df2_A['Quantity_str'] = df2_A['Quantity'].astype(int).astype(str)
df2_B['Quantity_str'] = df2_B['Quantity'].astype(int).astype(str)

# 生成拼接列
df2_A['A_Concate'] = df2_A['Name'] + df2_A['Date_str'] + df2_A['Quantity_str']
df2_B['B_Concate'] = df2_B['Name'] + df2_B['Date_str'] + df2_B['Quantity_str']

# 2. 整体匹配判断
df2_A['Match with B?'] = df2_A['A_Concate'].isin(df2_B['B_Concate']).map({True: 'Yes', False: 'No'})

# 3. 预处理B的数据,创建快速查询映射(适配一对多/多对多关系)
B_name_set = set(df2_B['Name'].unique())
# 每个Name对应的所有Date集合
B_name_to_dates = df2_B.groupby('Name')['Date_str'].apply(set).to_dict()
# 每个(Name, Date)对应的所有Quantity集合
B_name_date_to_qtys = df2_B.groupby(['Name', 'Date_str'])['Quantity_str'].apply(set).to_dict()

# 4. 按优先级判断各字段匹配状态
# 判断Name匹配情况
df2_A['Match name?'] = np.where(
    df2_A['Match with B?'] == 'Yes',
    'Match name',
    np.where(df2_A['Name'].isin(B_name_set), 'Match name', 'Not match name')
)

# 判断Date匹配情况(仅当Name匹配时才检查)
df2_A['Match date?'] = np.where(
    df2_A['Match with B?'] == 'Yes',
    'Match date',
    np.where(
        df2_A['Match name?'] == 'Not match name',
        'Match date',  # Name已不匹配,Date是否匹配不影响核心原因
        df2_A.apply(lambda row: 'Match date' if row['Date_str'] in B_name_to_dates.get(row['Name'], set()) else 'Not match date', axis=1)
    )
)

# 判断Quantity匹配情况(仅当Name和Date都匹配时才检查)
df2_A['Match quantity?'] = np.where(
    df2_A['Match with B?'] == 'Yes',
    'Match quantity',
    np.where(
        df2_A['Match name?'] == 'Not match name',
        'Match quantity',
        np.where(
            df2_A['Match date?'] == 'Not match date',
            'Match quantity',
            df2_A.apply(lambda row: 'Match quantity' if row['Quantity_str'] in B_name_date_to_qtys.get((row['Name'], row['Date_str']), set()) else 'Not match quantity', axis=1)
        )
    )
)

# 清理临时辅助列
df2_A.drop(columns=['Date_str', 'Quantity_str'], inplace=True)
df2_B.drop(columns=['Date_str', 'Quantity_str'], inplace=True)

关键优化点说明

  1. 统一数据格式:将Date转为固定格式的字符串,Quantity统一转int后再转字符串,彻底避免因格式/类型差异导致的无效不匹配。
  2. 预处理映射表:通过分组创建Name→Date、(Name,Date)→Quantity的集合映射,利用集合O(1)的查询效率,适配一对多/多对多的数据场景,避免逐行全表扫描。
  3. 明确逻辑优先级:按照Name→Date→Quantity的顺序判断,只有前一个字段匹配时才检查下一个字段,符合整体不匹配的原因排查逻辑。
  4. 向量化+按需apply:优先使用np.where做向量化判断,仅在需要关联映射表时使用apply,平衡代码可读性与执行效率。
  5. 边界情况处理:当Name已不匹配时,直接标记Date和Quantity为匹配(因为核心不匹配原因是Name),避免误判。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:45:02