如何比较两个DataFrame并返回差异列?解决形状不匹配报错
解决DataFrame对比时的"Can only compare identically-labeled DataFrame objects"报错
我来帮你搞定这个问题!你遇到的报错核心原因很明确:两年的员工技能DataFrame没有对齐——第二年的新入职员工、新增技能在第一年的数据里不存在,反过来第一年有的员工-技能组合第二年可能也消失了,导致两个表的行结构完全不匹配,自然没法直接用!=做对比。
下面是修正后的完整方案,核心思路是先构建一个包含所有员工+所有技能的完整组合索引,再把两年的数据都对齐到这个索引上,补全缺失值后再进行对比:
步骤1:提取两年的原始数据
先把两年的数据单独提取出来,保留必要字段:
import pandas as pd # 保留需要的字段 dataset = dataset[['Employee Name', 'Skill Name', 'Year', 'Score']] min_y = dataset['Year'].min() max_y = dataset['Year'].max() # 提取两年的原始数据(暂时保留Year字段) ds1_raw = dataset[dataset['Year'] == min_y] ds2_raw = dataset[dataset['Year'] == max_y]
步骤2:构建完整的员工-技能组合索引
我们需要把两年里出现过的所有员工和所有技能做笛卡尔积,得到所有可能的员工-技能组合,这样就能覆盖所有情况:
# 获取两年里所有唯一的员工和技能 all_employees = pd.concat([ds1_raw['Employee Name'], ds2_raw['Employee Name']]).unique() all_skills = pd.concat([ds1_raw['Skill Name'], ds2_raw['Skill Name']]).unique() # 生成完整的员工-技能组合索引 full_index = pd.MultiIndex.from_product( [all_employees, all_skills], names=['Employee Name', 'Skill Name'] )
步骤3:对齐两年的数据到完整索引
把两年的数据都重新索引到上面的完整组合上,缺失的技能评分用NaN填充(你也可以根据需求换成0,不过NaN更能代表"该员工当时未拥有此技能"的状态):
# 转换为以员工-技能为索引的结构,再重新索引补全缺失项 ds1 = ds1_raw.set_index(['Employee Name', 'Skill Name'])['Score'].reindex(full_index).reset_index() ds2 = ds2_raw.set_index(['Employee Name', 'Skill Name'])['Score'].reindex(full_index).reset_index() # 可选:按员工和技能排序,让结果更整齐 ds1 = ds1.sort_values(['Employee Name', 'Skill Name'], ascending=[True, False]) ds2 = ds2.sort_values(['Employee Name', 'Skill Name'], ascending=[True, False])
步骤4:对比差异并整理结果
现在两个DataFrame的形状完全一致了,可以放心对比差异。这里我们把缺失值(新增/消失的技能/员工)也视为差异:
# 找出差异(把NaN的情况也标记为差异) dsBool = (ds1['Score'] != ds2['Score']).replace({pd.NA: True}) # 拼接旧值和新值 dsdiff = pd.concat([ds1[dsBool], ds2[dsBool]], axis=1) dsdiff.columns = ["Old Score", "New Score"]
这样处理后,你不仅能看到已有员工技能评分的变化,还能清晰看到新增的员工、新增的技能(旧值为NaN),以及消失的员工/技能(新值为NaN)。
内容的提问来源于stack exchange,提问作者psowa001
相关产品推荐
相关产品推荐

