首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >比较两个DataFrames并并排输出它们的差异

比较两个DataFrames并并排输出它们的差异
EN

Stack Overflow用户
提问于 2013-06-14 03:08:17
回答 14查看 292.5K关注 0票数 207

我试图强调两个数据帧之间到底发生了什么变化。

假设我有两个Python Pandas数据帧:

代码语言:javascript
复制
"StudentRoster Jan-1":
id   Name   score                    isEnrolled           Comment
111  Jack   2.17                     True                 He was late to class
112  Nick   1.11                     False                Graduated
113  Zoe    4.12                     True       

"StudentRoster Jan-2":
id   Name   score                    isEnrolled           Comment
111  Jack   2.17                     True                 He was late to class
112  Nick   1.21                     False                Graduated
113  Zoe    4.12                     False                On vacation

我的目标是输出一个HTML表,该表:

HTML表识别已经改变的行(可以是int、float、布尔、具有相同、旧和新值的string)

  • Outputs行(理想情况下进入表),这样消费者就可以清楚地看到两个
  1. 之间发生了什么变化:

"StudentRoster Difference Jan-1 - Jan-2":id Name score isEnrolled Comment 112尼克是1.11|现在是1.21假毕业113佐伊4.12是真|现在假是"“|现在在度假”“

我想我可以逐行和逐列进行比较,但是有没有更简单的方法呢?

EN

回答 14

Stack Overflow用户

回答已采纳

发布于 2013-06-14 03:39:45

第一部分类似于Constantine,您可以获得哪些行为空的布尔值*

代码语言:javascript
复制
In [21]: ne = (df1 != df2).any(1)

In [22]: ne
Out[22]:
0    False
1     True
2     True
dtype: bool

然后,我们可以看到哪些条目发生了更改:

代码语言:javascript
复制
In [23]: ne_stacked = (df1 != df2).stack()

In [24]: changed = ne_stacked[ne_stacked]

In [25]: changed.index.names = ['id', 'col']

In [26]: changed
Out[26]:
id  col
1   score         True
2   isEnrolled    True
    Comment       True
dtype: bool

在这里,第一个条目是索引,第二个条目是已更改的列。

代码语言:javascript
复制
In [27]: difference_locations = np.where(df1 != df2)

In [28]: changed_from = df1.values[difference_locations]

In [29]: changed_to = df2.values[difference_locations]

In [30]: pd.DataFrame({'from': changed_from, 'to': changed_to}, index=changed.index)
Out[30]:
               from           to
id col
1  score       1.11         1.21
2  isEnrolled  True        False
   Comment     None  On vacation

*注意:重要的是df1df2在这里共享相同的索引。为了克服这种模糊性,您可以确保只使用df1.index & df2.index查看共享标签,但我认为这将作为练习。

票数 168
EN

Stack Overflow用户

发布于 2017-11-04 22:58:06

突出显示两个DataFrames之间的差异

可以使用DataFrame style属性突出显示存在差异的单元格的背景色。

使用原始问题中的示例数据的

第一步是使用concat函数水平连接DataFrames,并使用keys参数区分每个帧:

代码语言:javascript
复制
df_all = pd.concat([df.set_index('id'), df2.set_index('id')], 
                   axis='columns', keys=['First', 'Second'])
df_all

交换列级别并将相同的列名放在彼此的旁边可能更容易:

代码语言:javascript
复制
df_final = df_all.swaplevel(axis='columns')[df.columns[1:]]
df_final

现在,更容易发现帧之间的差异。但是,我们可以更进一步,使用style属性来突出显示不同的单元格。我们定义了一个自定义函数来做这件事,你可以在this part of the documentation中看到。

代码语言:javascript
复制
def highlight_diff(data, color='yellow'):
    attr = 'background-color: {}'.format(color)
    other = data.xs('First', axis='columns', level=-1)
    return pd.DataFrame(np.where(data.ne(other, level=0), attr, ''),
                        index=data.index, columns=data.columns)

df_final.style.apply(highlight_diff, axis=None)

这将突出显示两个都缺少值的单元格。您可以填充它们,也可以提供额外的逻辑,这样它们就不会突出显示。

票数 120
EN

Stack Overflow用户

发布于 2016-07-17 21:12:43

这个答案只是简单地扩展了@Andy Hayden的答案,使其在数值字段为nan时具有弹性,并将其包装到一个函数中。

代码语言:javascript
复制
import pandas as pd
import numpy as np


def diff_pd(df1, df2):
    """Identify differences between two pandas DataFrames"""
    assert (df1.columns == df2.columns).all(), \
        "DataFrame column names are different"
    if any(df1.dtypes != df2.dtypes):
        "Data Types are different, trying to convert"
        df2 = df2.astype(df1.dtypes)
    if df1.equals(df2):
        return None
    else:
        # need to account for np.nan != np.nan returning True
        diff_mask = (df1 != df2) & ~(df1.isnull() & df2.isnull())
        ne_stacked = diff_mask.stack()
        changed = ne_stacked[ne_stacked]
        changed.index.names = ['id', 'col']
        difference_locations = np.where(diff_mask)
        changed_from = df1.values[difference_locations]
        changed_to = df2.values[difference_locations]
        return pd.DataFrame({'from': changed_from, 'to': changed_to},
                            index=changed.index)

因此,对于您的数据(稍微编辑一下,在score列中有一个NaN ):

代码语言:javascript
复制
import sys
if sys.version_info[0] < 3:
    from StringIO import StringIO
else:
    from io import StringIO

DF1 = StringIO("""id   Name   score                    isEnrolled           Comment
111  Jack   2.17                     True                 "He was late to class"
112  Nick   1.11                     False                "Graduated"
113  Zoe    NaN                     True                  " "
""")
DF2 = StringIO("""id   Name   score                    isEnrolled           Comment
111  Jack   2.17                     True                 "He was late to class"
112  Nick   1.21                     False                "Graduated"
113  Zoe    NaN                     False                "On vacation" """)
df1 = pd.read_table(DF1, sep='\s+', index_col='id')
df2 = pd.read_table(DF2, sep='\s+', index_col='id')
diff_pd(df1, df2)

输出:

代码语言:javascript
复制
                from           to
id  col                          
112 score       1.11         1.21
113 isEnrolled  True        False
    Comment           On vacation
票数 57
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17095101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档