Pandas单元测试: 如何断言NaT和NaN值的相等性?

5
在NumPy和Pandas中,nan != nanNaT != NaT。因此,在单元测试期间比较结果时,如何断言返回值是其中之一?一个简单的assertEqual自然会失败,即使我使用pandas.util.testing

2
使用isnull函数。 - EdChum
只需简单地将“value!= value”写入代码,就应该返回真。 - Hacketo
3个回答

7

如果你要比较标量,一种方法是使用assertTrueisnull。例如,在DataFrame单元测试(pandas/tests/test_frame.py)中,你可以找到像这样的测试

self.assertTrue(com.isnull(df.ix['c', 'timestamp']))

(compandas/core/common.py 的别名,因此 com.isnull 调用与 pd.isnull 相同的基础函数。)

另一方面,如果您要比较具有空值的 Series 或 DataFrame 是否相等,则可以使用 tm.assert_series_equaltm.assert_frame_equal 自动处理这些情况。例如:

>>> import pandas.util.testing as tm
>>> df = pd.DataFrame({'a': [1, np.nan]})
>>> df
    a
0   1
1 NaN

通常情况下,NaN 不等于 NaN
>>> df == df
       a
0   True
1  False

但是assert_frame_equal处理NaN时会将其视为等于自身:

>>> tm.assert_frame_equal(df, df)
# no AssertionError raised

3
在进行assert_frame_equal检查之前,您可以使用.fillna()方法对数据框中的空值进行替换,以便用其他不会出现在您的值中的内容代替。您还可以阅读这些示例,了解如何使用.fillna()方法。

1
谢谢,这几乎就是我一直在寻找的。我说“几乎”是因为你不能传递 None,它本应作为一种类型中立的值,但另一个唯一的标量,比如零或字符串(例如 "INCORRECT!!!1!1!" ;-) ),现在已经足够好了。 - Berislav Lopac
@BerislavLopac:也许我误解了你要做的事情,但是assert_frame_equal已经断言了NaN等于NaN。使用fillna()NaN替换为其他标量进行比较是多余的,因此在Pandas的单元测试中不会使用。 - Alex Riley
哎呀,你说得对 - 我太过于字面理解你的建议并在 assert_frame_check 之前调用了 fillna,所以我错过了它可以解决差异的事实。谢谢! - Berislav Lopac
@Alex,为了改进你的回答,你可以通过使用object()来轻松强制一个“在你的值中不会出现的其他东西”。如果你定义一个变量并将object()赋值给它,然后在fillna方法和AssertEqual方法中使用这个变量 - 这样既解决了原始问题,又确保你对nan的比较没有意外地捕捉到其他情况。 - undefined

3

在 Python2.7 上进行测试,我得到了以下结果:

import numpy as np
import pandas as pd

x = np.nan
x is np.nan #True
x is pd.NaT #False
np.isnan(x) #True
pd.isnull(x) #True

y = pd.NaT
y is np.nan #False
y is pd.NaT #True
np.isnan(y) #TypeError !!
pd.isnull(y) #True

你也可以使用
x != x #True for nan
y != y #True for NaT

但我并不是很喜欢这种风格,我总是无法完全相信它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接