Pandas DataFrames与NaNs相等比较

Ste*_*ike 26 python equality nan pandas

在单元测试一些函数的上下文中,我试图使用python pandas建立2个DataFrame的相等性:

ipdb> expect
                            1   2
2012-01-01 00:00:00+00:00 NaN   3
2013-05-14 12:00:00+00:00   3 NaN

ipdb> df
identifier                  1   2
timestamp
2012-01-01 00:00:00+00:00 NaN   3
2013-05-14 12:00:00+00:00   3 NaN

ipdb> df[1][0]
nan

ipdb> df[1][0], expect[1][0]
(nan, nan)

ipdb> df[1][0] == expect[1][0]
False

ipdb> df[1][1] == expect[1][1]
True

ipdb> type(df[1][0])
<type 'numpy.float64'>

ipdb> type(expect[1][0])
<type 'numpy.float64'>

ipdb> (list(df[1]), list(expect[1]))
([nan, 3.0], [nan, 3.0])

ipdb> df1, df2 = (list(df[1]), list(expect[1])) ;; df1 == df2
False
Run Code Online (Sandbox Code Playgroud)

鉴于我试图expect对整个(df包括NaN职位)进行全面测试,我做错了什么?

比较包括NaNs 的Series/DataFrames的相等性的最简单方法是什么?

And*_*den 29

您可以将assert_frame_equals与check_names = False一起使用(以便不检查索引/列名称),如果它们不相等则会引发:

In [11]: from pandas.testing import assert_frame_equal

In [12]: assert_frame_equal(df, expected, check_names=False)
Run Code Online (Sandbox Code Playgroud)

你可以将它包装在一个函数中,例如:

try:
    assert_frame_equal(df, expected, check_names=False)
    return True
except AssertionError:
    return False
Run Code Online (Sandbox Code Playgroud)

在最近的大熊猫中,此功能已添加为.equals:

df.equals(expected)
Run Code Online (Sandbox Code Playgroud)


Phi*_*oud 17

其中一个特性NaN是,NaN != NaNTrue.

看看这个答案是一个很好的方法来使用它numexpr.

(a == b) | ((a != a) & (b != b))
Run Code Online (Sandbox Code Playgroud)

说这个(伪代码):

a == b or (isnan(a) and isnan(b))
Run Code Online (Sandbox Code Playgroud)

所以,要么a等于b或两者abNaN.

如果你有小框架,那就assert_frame_equal没关系.但是,对于大型框架(10M行)assert_frame_equal来说几乎没用.我不得不打断它,这花了很长时间.

In [1]: df = DataFrame(rand(1e7, 15))

In [2]: df = df[df > 0.5]

In [3]: df2 = df.copy()

In [4]: df
Out[4]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10000000 entries, 0 to 9999999
Columns: 15 entries, 0 to 14
dtypes: float64(15)

In [5]: timeit (df == df2) | ((df != df) & (df2 != df2))
1 loops, best of 3: 598 ms per loop
Run Code Online (Sandbox Code Playgroud)

timeit(推测)所需单一的,bool表示两者DataFrame是否相等:

In [9]: timeit ((df == df2) | ((df != df) & (df2 != df2))).values.all()
1 loops, best of 3: 687 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • 你可以这样做 ``((df == df2) | ((df != df) &amp; (df2 != df2))).values.ravel().all()`` (2认同)

Jef*_*eff 9

像@PhillipCloud 的回答,但写得更多

In [26]: df1 = DataFrame([[np.nan,1],[2,np.nan]])

In [27]: df2 = df1.copy()
Run Code Online (Sandbox Code Playgroud)

他们真的是等价的

In [28]: result = df1 == df2

In [29]: result[pd.isnull(df1) == pd.isnull(df2)] = True

In [30]: result
Out[30]: 
      0     1
0  True  True
1  True  True
Run Code Online (Sandbox Code Playgroud)

df2 中的 nan 在 df1 中不存在

In [31]: df2 = DataFrame([[np.nan,1],[np.nan,np.nan]])

In [32]: result = df1 == df2

In [33]: result[pd.isnull(df1) == pd.isnull(df2)] = True

In [34]: result
Out[34]: 
       0     1
0   True  True
1  False  True
Run Code Online (Sandbox Code Playgroud)

您还可以填充一个您知道不在框架中的值

In [38]: df1.fillna(-999) == df1.fillna(-999)
Out[38]: 
      0     1
0  True  True
1  True  True
Run Code Online (Sandbox Code Playgroud)

  • 如果你有两个不相等的值,我认为这会给出 True,因为它们都是非空的:s (3认同)
  • @Andy Hayden是正确的:`result[pd.isnull(df1) == pd.isnull(df2)] = True`应该是`result[pd.isnull(df1) &amp; pd.isnull(df2)] = True` (2认同)

Lyd*_*dia 6

使用 == 与 np.NaN 进行任何相等比较都是 False,甚至 np.NaN == np.NaN 也是 False。

简单地说df1.fillna('NULL') == df2.fillna('NULL'),如果“NULL”不是原始数据中的值。

为了安全起见,请执行以下操作:

示例 a) 比较两个具有 NaN 值的数据帧

bools = (df1 == df2)
bools[pd.isnull(df1) & pd.isnull(df2)] = True
assert bools.all().all()
Run Code Online (Sandbox Code Playgroud)

示例 b) 过滤 df1 中与 df2 不匹配的行

bools = (df1 != df2)
bools[pd.isnull(df1) & pd.isnull(df2)] = False
df_outlier = df1[bools.all(axis=1)]
Run Code Online (Sandbox Code Playgroud)

(注意:这是错误的 - bools[pd.isnull(df1) == pd.isnull(df2)] = False)

  • 如果您在答案中添加更多文字(也许可以解释您在做什么),您的答案会看起来更好。 (2认同)