如何用Pandas检测两个DataFrame行级别列变更并生成明细?
解决思路与完整代码
你已经完成了合并DataFrame的基础步骤,现在我们可以通过矢量化操作(比逐行apply更高效)来批量生成变更检测和描述列,避免重复写多个函数。下面是完整的实现方案:
步骤1:导入依赖并创建示例数据
首先确保你导入了pandas和numpy:
import pandas as pd import numpy as np # 示例DataFrame 1 df1 = pd.DataFrame({ 'NAME': ['Jason Kelly', 'Jon Gilman', 'Jessica Lang', 'Bob Wilder', 'Samir Bala'], 'EMAIL': ['jasonkelly@123.com', 'jongilman@123.com', 'jessicalang@123.com', 'bobwilder@123.com', 'samirbala@123.com'], 'COUNTRY': ['USA', 'CANADA', 'AUSTRALIA', 'ROMANIA', 'CANADA'], 'JOBCODE': [1221, 1222, 1221, 1355, 1221], 'MANAGERNAME': ['Jon Gilman', 'Cindy Lee', 'Esther Donato', 'Mike Lens', 'Ricky Easton'] }) # 示例DataFrame 2 df2 = pd.DataFrame({ 'NAME': ['Jason Kelly', 'Jon Gilman', 'Jessica Lang', 'Bob Wilder', 'Samir Bala'], 'EMAIL': ['jasonkelly@123.com', 'jongilman@123.com', 'jessicalang@123.com', 'bobwilder@123.com', 'samirbala@123.com'], 'COUNTRY': ['VIETNAM', 'CANADA', 'AUSTRALIA', 'ROMANIA', 'CANADA'], 'JOBCODE': [1221, 4464, 2224, 1355, 1221], 'MANAGERNAME': ['Jon Gilman', 'Sheldon Tracey', 'Esther Donato', 'Emilia Tanner', 'Ricky Easton'] })
步骤2:合并并生成变更列
我们先合并两个DataFrame,然后对COUNTRY、JOBCODE、MANAGERNAME三个列分别生成「是否变更」和「变更内容」列:
# 按EMAIL合并两个DataFrame(只保留共同存在的邮箱) dfmerge = pd.merge(df1, df2, how='inner', on='EMAIL', suffixes=('_old', '_new')) # 定义处理单个列变更的逻辑 def generate_change_columns(df, col_name): # 生成是否变更列 change_col = f"{col_name}_CHANGE" df[change_col] = np.where(df[f"{col_name}_old"] != df[f"{col_name}_new"], 'YES', 'NO') # 生成变更描述列 movement_col = f"{col_name}_MOVEMENT" df[movement_col] = np.where( df[change_col] == 'YES', df.apply(lambda row: f"FROM {row[f'{col_name}_old']} TO {row[f'{col_name}_new']}", axis=1), 'NO' ) # 批量处理三个目标列 for col in ['COUNTRY', 'JOBCODE', 'MANAGERNAME']: generate_change_columns(dfmerge, col) # 整理最终输出的列(只保留需要的字段) result_df = dfmerge[[ 'EMAIL', 'COUNTRY_CHANGE', 'COUNTRY_MOVEMENT', 'JOBCODE_CHANGE', 'JOBCODE_MOVEMENT', 'MANAGERNAME_CHANGE', 'MANAGERNAME_MOVEMENT' ]] # 重命名MANAGER相关列(和你的期望输出对齐) result_df = result_df.rename(columns={ 'MANAGERNAME_CHANGE': 'MGR_CHANGE', 'MANAGERNAME_MOVEMENT': 'MGR_MOVEMENT' }) print(result_df)
输出结果
运行后你会得到和你期望完全一致的结果:
EMAIL COUNTRY_CHANGE COUNTRY_MOVEMENT JOBCODE_CHANGE JOBCODE_MOVEMENT MGR_CHANGE MGR_MOVEMENT 0 jasonkelly@123.com YES FROM USA TO VIETNAM NO NO NO NO 1 jongilman@123.com NO NO YES FROM 1222 TO 4464 YES FROM Cindy Lee TO Sheldon Tracey 2 jessicalang@123.com NO NO YES FROM 1221 TO 2224 NO NO 3 bobwilder@123.com NO NO NO NO YES FROM Mike Lens TO Emilia Tanner 4 samirbala@123.com NO NO NO NO NO NO
关键说明
- 用
numpy.where做矢量化判断,比apply(axis=1)效率高很多,适合大数据量场景; - 封装了通用函数
generate_change_columns,避免重复代码,后续要加其他列的话直接在循环里加即可; - 通过
suffixes参数给合并后的列加_old和_new后缀,更清晰区分新旧数据; - 最后重命名了经理相关的列,和你的期望输出格式对齐。
内容的提问来源于stack exchange,提问作者wjie08
相关产品推荐
相关产品推荐

