Pandas DataFrames中的平等 - 列顺序很重要?

jcr*_*udy 22 python pandas

作为单元测试的一部分,我需要测试两个DataFrames是否相等.DataFrame中列的顺序对我来说并不重要.然而,对熊猫来说似乎很重要:

import pandas
df1 = pandas.DataFrame(index = [1,2,3,4])
df2 = pandas.DataFrame(index = [1,2,3,4])
df1['A'] = [1,2,3,4]
df1['B'] = [2,3,4,5]
df2['B'] = [2,3,4,5]
df2['A'] = [1,2,3,4]
df1 == df2
Run Code Online (Sandbox Code Playgroud)

结果是:

Exception: Can only compare identically-labeled DataFrame objects
Run Code Online (Sandbox Code Playgroud)

我相信表达式df1 == df2应该评估为包含所有True值的DataFrame .显然,==在这种情况下,正确的功能应该是有争议的.我的问题是:是否有一个Pandas方法可以满足我的需求?也就是说,有没有办法进行忽略列顺序的相等比较?

Qua*_*ant 31

最常见的意图是这样处理的:

def assertFrameEqual(df1, df2, **kwds ):
    """ Assert that two dataframes are equal, ignoring ordering of columns"""
    from pandas.util.testing import assert_frame_equal
    return assert_frame_equal(df1.sort_index(axis=1), df2.sort_index(axis=1), check_names=True, **kwds )
Run Code Online (Sandbox Code Playgroud)

当然,请参阅pandas.util.testing.assert_frame_equal您可以传递的其他参数

  • 别排序。传递 `check_like` 参数。查看其他答案。 (2认同)

And*_*den 14

您可以使用sort_index以下方式对列进

df1.sort_index(axis=1) == df2.sort_index(axis=1)
Run Code Online (Sandbox Code Playgroud)

这将评估所有True值的数据帧.


由于@osa评论这对于NaN来说是失败的并且也不是特别强大,实际上可能建议使用类似于@ quant的答案(注意:如果有问题,我们想要一个bool而不是加注):

def my_equal(df1, df2):
    from pandas.util.testing import assert_frame_equal
    try:
        assert_frame_equal(df1.sort_index(axis=1), df2.sort_index(axis=1), check_names=True)
        return True
    except (AssertionError, ValueError, TypeError):  perhaps something else?
        return False
Run Code Online (Sandbox Code Playgroud)


小智 9

assert_frame_equalfrompandas.testing是一个检查帧相等性的函数。如assert_frame_equal 文档中所述,如果将check_like参数设置为True,它将忽略索引和列的顺序。


Mur*_*nch 6

通常,您需要快速测试,而对于较大的索引,排序方法可能效率极低(例如,如果您使用行而不是列来解决此问题)。排序方法还容易受到非唯一索引的漏报的影响。

\n\n

幸运的是,pandas.util.testing.assert_frame_equal此后已更新了一个check_like选项。将其设置为 true,测试中将不考虑排序。

\n\n

使用非唯一索引,您将获得神秘的ValueError: cannot reindex from a duplicate axis. reindex_like这是由重新排列其中一个 DataFrame 以匹配另一个 DataFrame 的顺序的底层操作引起的。重新索引很多,如下所示。

\n\n
import pandas as pd\nfrom pandas.util.testing import assert_frame_equal\n\ndf  = pd.DataFrame(np.arange(1e6))\ndf1 = df.sample(frac=1, random_state=42)\ndf2 = df.sample(frac=1, random_state=43)\n\n%timeit -n 1 -r 5 assert_frame_equal(df1.sort_index(), df2.sort_index())\n## 5.73 s \xc2\xb1 329 ms per loop (mean \xc2\xb1 std. dev. of 5 runs, 1 loop each)\n\n%timeit -n 1 -r 5 assert_frame_equal(df1, df2, check_like=True)\n## 1.04 s \xc2\xb1 237 ms per loop (mean \xc2\xb1 std. dev. of 5 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于那些喜欢良好性能比较图的人:

\n\n

重新索引与 int 和 str 索引排序(str 更剧烈)

\n


Qua*_*ant 5

def equal( df1, df2 ):
    """ Check if two DataFrames are equal, ignoring nans """
    return df1.fillna(1).sort_index(axis=1).eq(df2.fillna(1).sort_index(axis=1)).all().all()
Run Code Online (Sandbox Code Playgroud)