【问题标题】:How to compare two dataframes and return a column with difference?如何比较两个数据框并返回有差异的列?
【发布时间】:2019-08-30 08:45:12
【问题描述】:

我正在准备一个数据框来存储员工技能的变化。

我想比较带有以下标签的两个表:“员工姓名”、“技能名称”、“年份”和“分数”。在第二年雇用了一些员工,并增加了一些技能。我想检查两个数据框中是否缺少员工或技能并填补空白,以便数据框的形状相同。

dataset = dataset[['Employee Name', 'Skill Name', 'Year', 'Score']]

min_y = dataset['Year'].min()
max_y = dataset['Year'].max()

ds1 = ds1.sort_values(['Employee Name', 'Skill Name'], ascending=[True, False])
ds2 = ds2.sort_values(['Employee Name', 'Skill Name'], ascending=[True, False])

ds1 = dataset[dataset['Year']==min_y].reset_index().drop(['index'], axis=1).drop(['Year'], axis=1)
ds2 = dataset[dataset['Year']==max_y].reset_index().drop(['index'], axis=1).drop(['Year'], axis=1)

dsBool = (ds1 != ds2).stack()
dsdiff = pd.concat([ds1.stack()[dsBool], ds2.stack()[dsBool]], axis=1)
dsdiff.columns=["Old", "New"]

目前比较这两个表会因为两个DataFrame的形状不同而导致错误: 只能比较具有相同标签的 DataFrame 对象

【问题讨论】:

  • 什么是df1.indexds2.index 在您尝试比较之前?它们匹配吗?
  • 出现这个错误:Lengths must match to compare
  • 是的,但是你能发布比较之前的ds1.indexds1.index 是什么,即在dsBool = (ds1 != ds2).stack() 之前
  • python Int64Index([567, 14, 505, 504, 13, 12, 566, 11, 503, 10, ... 806, 740, 739, 738, 737, 807, 736, 646, 497, 805], dtype='int64', length=825) Int64Index([ 778, 13, 539, 12, 11, 10, 538, 954, 956, 955, ... 1242, 1241, 1244, 1240, 1239, 1123, 951, 950, 1238, 768], dtype='int64', length=1289)
  • 如果您提供两个数据框的样本,会更容易回答。

标签: python pandas


【解决方案1】:

据了解,形状错误是由于增加了新员工和更新现有员工的技能。要找出缺失值,您可以加入这些数据框,然后删除重复的条目。这样,剩下的唯一条目将是两个数据帧中不同的条目。

temp = pd.concat((ds1, ds2), axis = 0)
temp = temp.drop_duplicates(subset = 'Employee Name', keep = False, inplace = True)
# keep = False ensures that all repeating entries are considered duplicates

临时数据帧现在包含在最初的 2 个数据帧中不同的所有条目。可以在其形状匹配的数据框中搜索和编辑它们。

【讨论】:

  • 此代码的输出是只有一个“分数”列的数据框,所以我无法计算年份之间的差异
  • 尝试通过仅比较员工姓名来删除重复项。我已经为它编辑了代码。
  • 我使用了我们的代码,输出 temp.columns 为:Index(['Employee Name', 'Skill Name', 'Score'], dtype='object')
【解决方案2】:

在比较之前尝试确保两个数据帧的索引相同:

ds1 = dataset[dataset['Year']==min_y].drop(['Year'], axis=1).reset_index(drop=True)
ds2 = dataset[dataset['Year']==max_y].drop(['Year'], axis=1).reset_index(drop=True)

然后进行比较:

dsBool = (ds1 != ds2).stack()

编辑:

实际上,我认为您的原始帖子的代码顺序可能错误。请尝试以下操作:

dataset = dataset[['Employee Name', 'Skill Name', 'Year', 'Score']]

dataset.sort_values(['Employee Name', 'Skill Name'], ascending=[True, False], inplace=True)

ds1 = dataset[dataset['Year'] == dataset['Year'].min()].drop(['Year'], axis=1).reset_index(drop=True)
ds2 = dataset[dataset['Year'] == dataset['Year'].max()].drop(['Year'], axis=1).reset_index(drop=True)

dsBool = (ds1 != ds2).stack()
dsdiff = pd.concat([ds1.stack()[dsBool], ds2.stack()[dsBool]], axis=1)
dsdiff.columns=["Old", "New"]

【讨论】:

  • 发生错误:只能比较标记相同的DataFrame对象
  • @psowa001 您的列名不能如此匹配。 ds1.columnsds2.columns 的输出是什么?
  • ds1.columns: Index(['Employee Name', 'Skill Name', 'Score'], dtype='object') ds2.columns: Index(['Employee Name', 'Skill Name', 'Score'], dtype='object')
猜你喜欢
  • 2019-08-22
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2021-08-30
  • 2013-08-08
相关资源
最近更新 更多