【问题标题】:Pandas df.equals() returning False on identical dataframes?Pandas df.equals() 在相​​同的数据帧上返回 False?
【发布时间】:2020-12-16 13:34:59
【问题描述】:

df_1df_2 为:

In [1]: import pandas as pd
   ...: df_1 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
   ...: df_2 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})

In [2]: df_1
Out[2]:
   a  b
0  1  4
1  2  5
2  3  6

我们在df_1 中添加一行r

In [3]: r = pd.DataFrame({'a': ['x'], 'b': ['y']})
   ...: df_1 = df_1.append(r, ignore_index=True)

In [4]: df_1
Out[4]:
   a  b
0  1  4
1  2  5
2  3  6
3  x  y

我们现在从df_1 中删除添加的行,并重新获得原来的df_1

In [5]: df_1 = pd.concat([df_1, r]).drop_duplicates(keep=False)

In [6]: df_1
Out[6]:
   a  b
0  1  4
1  2  5
2  3  6

In [7]: df_2
Out[7]:
   a  b
0  1  4
1  2  5
2  3  6

虽然df_1df_2 相同,但equals() 返回False

In [8]: df_1.equals(df_2)
Out[8]: False

对 SO 进行了研究,但找不到相关问题。 我做错了吗?在这种情况下如何得到正确的结果? (df_1==df_2).all().all() 返回True 但不适用于df_1df_2 长度不同的情况。

【问题讨论】:

    标签: python pandas dataframe equals dtype


    【解决方案1】:

    这又是一个微妙的问题,很好地发现了它。

    import pandas as pd
    df_1 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
    df_2 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
    r = pd.DataFrame({'a': ['x'], 'b': ['y']})
    df_1 = df_1.append(r, ignore_index=True)
    df_1 = pd.concat([df_1, r]).drop_duplicates(keep=False)
    df_1.equals(df_2)
    
    from pandas.util.testing import assert_frame_equal
    assert_frame_equal(df_1,df_2)
    

    现在我们可以看到断言失败的问题。

    AssertionError: Attributes of DataFrame.iloc[:, 0] (column name="a") are different
    
    Attribute "dtype" are different
    [left]:  object
    [right]: int64
    

    当您将字符串添加到整数时,整数变成了对象。所以这就是equals失败的原因..

    【讨论】:

    • 谢谢!背后的原因是什么?怎么可能被忽视? (df_1==df_2).all().all() 返回True 但不适用于df_1df_2 长度不同的情况。
    • 将它们转换为相同的类型,然后查看它们是否相等。通常,我尝试只保留一次数据,但如果您要获取另一组数据,检查它们是否相同 dtype 是一件好事,让它们相同更好。
    • df_1['a'] = df_1['a'].astype(int) df_1['b'] = df_1['b'].astype(int) print(df_1.equals(df_2)) 会给你你想要的答案。
    【解决方案2】:

    使用pandas.testing.assert_frame_equal(df_1, df_2, check_dtype=True),它还会检查dtypes是否相同。

    (在这种情况下,当您追加然后删除字符串行时,您的 dtypes 会从 int 更改为 'object'(字符串)。)

    AssertionError: Attributes of DataFrame.iloc[:, 0] (column name="a") are different
    
    Attribute "dtype" are different
    [left]:  object
    [right]: int64
    

    【讨论】:

      【解决方案3】:

      根据df.equals 文档:

      此功能允许将两个 Series 或 DataFrame 相互比较,以查看它们是否具有相同的形状和元素。同一位置的 NaN 被认为是相等的。列标题不需要具有相同的类型,但列中的元素必须具有相同的dtype

      因此,df.equals 将仅在元素具有相同值且 dtypes 也相同时返回 True

      当您从df_1 添加和删除行时,dtypes 会从int 更改为object,因此它返回False

      用你的例子解释:

      In [1028]: df_1 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
      
      In [1029]: df_2 = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
      
       In [1031]: df_1.dtypes
      Out[1031]: 
      a    int64
      b    int64
      dtype: object
      
      In [1032]: df_2.dtypes
      Out[1032]: 
      a    int64
      b    int64
      dtype: object
      

      因此,如果您在上面看到,两个 dfs 的 dtypes 相同,因此以下条件返回 True

      In [1030]: df_1.equals(df_2)
      Out[1030]: True
      

      现在添加和删除行之后:

      In [1033]: r = pd.DataFrame({'a': ['x'], 'b': ['y']})
      
      In [1034]: df_1 = df_1.append(r, ignore_index=True)
      
      In [1036]: df_1 = pd.concat([df_1, r]).drop_duplicates(keep=False)
      
      In [1038]: df_1.dtypes
      Out[1038]: 
      a    object
      b    object
      dtype: object
      

      dtype 已更改为 object,因此以下条件返回 False

      In [1039]: df_1.equals(df_2)
      Out[1039]: False
      

      如果你仍然希望它返回True,你需要将dtypes改回int

      In [1042]: df_1 = df_1.astype(int)
      In [1044]: df_1.equals(df_2)
      Out[1044]: True
      

      【讨论】:

        【解决方案4】:

        基于其他人的cmets,在这种情况下可以这样做:

        from pandas.util.testing import assert_frame_equal
        
        identical_df = True
        try:
            assert_frame_equal(df_1, df_2, check_dtype=False)
        except AssertionError:
            identical_df = False
        

        【讨论】:

          猜你喜欢
          • 2018-05-11
          • 1970-01-01
          • 2019-08-07
          • 1970-01-01
          • 2013-02-10
          • 2021-04-22
          • 2019-09-10
          • 2021-07-20
          • 1970-01-01
          相关资源
          最近更新 更多