【问题标题】:How to compare 2 non-identical dataframes in python如何在python中比较2个不同的数据框
【发布时间】:2022-01-13 22:04:21
【问题描述】:

我有两个列顺序相同但列名和行不同的数据框。 df2 行与 df1 行不同。

df1=     col_id  num  name
      0   1     3     linda
      1   2     4     James

df2=     id     no   name
      0   1     2    granpa
      1   2     6    linda
      2   3     7    sam

这是我需要的输出。输出具有相同、OLD 和 NEW 值的行,以便用户可以清楚地看到两个数据帧之间的变化:

 result   col_id        num              name   
      0   1             was 3| now 2    was linda| now granpa  
      1   2             was 4| now 6    was James| now linda
      2   was  | now 3  was  | now 7    was      | now sam

【问题讨论】:

  • 为什么 nans 在中间?
  • @user17242583 - 对此感到抱歉。我已经纠正了我的问题。请检查

标签: python pandas dataframe assert


【解决方案1】:

由于您的目标只是比较差异,因此请使用 DataFrame.compare 而不是聚合成字符串。

然而,

DataFrame.compare 只能比较具有相同标签(即相同形状、相同行和列标签)的 DataFrames

所以我们只需要通过merge 或reindex 对齐行/列索引。


通过merge对齐

  1. 外-merge两个dfs:

    merged = df1.merge(df2, how='outer', left_on='col_id', right_on='id')
    #    col_id  num  name_x  id  no  name_y
    # 0       1    3   linda   1   2  granpa
    # 1       2    4   james   2   6   linda
    # 2     NaN  NaN     NaN   3   7     sam
    
  2. 将merged 框架划分为left/right 框架并将它们的列与set_axis 对齐:

    cols = df1.columns
    left = merged.iloc[:, :len(cols)].set_axis(cols, axis=1)
    #    col_id  num    name
    # 0       1    3   linda
    # 1       2    4   james
    # 2     NaN  NaN     NaN
    
    right = merged.iloc[:, len(cols):].set_axis(cols, axis=1)
    #    col_id  num    name
    # 0       1    2  granpa
    # 1       2    6   linda
    # 2       3    7     sam
    
  3. compare 对齐的left/right 框架(使用keep_equal=True 显示相等的单元格):

    left.compare(right, keep_shape=True, keep_equal=True)
    #        col_id         num          name
    #    self other  self other   self  other
    # 0     1     1     3     2  linda granpa
    # 1     2     2     4     6  james  linda
    # 2   NaN     3   NaN     7    NaN    sam
    
    left.compare(right, keep_shape=True)
    #        col_id         num          name
    #    self other  self other   self  other
    # 0   NaN   NaN     3     2  linda granpa
    # 1   NaN   NaN     4     6  james  linda
    # 2   NaN     3   NaN     7    NaN    sam
    

通过reindex对齐

如果您 100% 确定一个 df 是另一个 df 的子集,那么 reindex 子集的行。

在您的示例中,df1 是df2 的子集,因此reindex df1:

df1.assign(id=df1.col_id)          # copy col_id (we need original col_id after reindexing)
   .set_index('id')                # set index to copied id
   .reindex(df2.id)                # reindex against df2's id
   .reset_index(drop=True)         # remove copied id
   .set_axis(df2.columns, axis=1)  # align column names
   .compare(df2, keep_equal=True, keep_shape=True)

#        col_id         num          name
#    self other  self other   self  other
# 0     1     1     3     2  linda granpa
# 1     2     2     4     6  james  linda
# 2   NaN     3   NaN     7    NaN    sam

可为空的整数

通常int 不能与nan 混合,因此pandas 转换为float。将int 值保持为int(如上面的示例):

【讨论】:

  • 你是个天才。美丽的描述,非常感谢您花时间了解我的问题并提供解决方案。后来我意识到我的列不同,而不是行,所以我不得不稍微调整一下,让 2 个数据帧相同,但你的解决方案很漂亮。
  • @EverydayLearner 太棒了,很高兴你能用它
【解决方案2】:

如果我理解正确,你想要这样的东西:

new_df = df1.drop(['name', 'num'], axis=1).merge(df2.rename({'id': 'col_id'}, axis=1), how='outer')

输出:

>>> new_df
   col_id  no    name
0       1   2  granpa
1       2   6   linda
2       3   7     sam

【讨论】:

  • 感谢@user17242583,我正在尝试为用户比较和捕捉 df1 和 df2 之间的差异。
猜你喜欢
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 2022-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多