Pandas DataFrames与NaNs相等性比较

aor9mmx1  于 2023-08-01  发布在  其他
关注(0)|答案(7)|浏览(113)

在单元测试某些函数的上下文中,我试图使用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

字符串
考虑到我试图测试整个expect和整个df,包括NaN的位置,我做错了什么?

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

gdx19jrr

gdx19jrr1#

你可以使用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)

字符串
你可以将它 Package 在一个函数中,如下所示:

try:
    assert_frame_equal(df, expected, check_names=False)
    return True
except AssertionError:
    return False


在最近的pandas中,这个功能被添加为.equals

df.equals(expected)

zz2j4svz

zz2j4svz2#

NaN的特性之一是NaN != NaNTrue
查看this answer,了解使用numexpr实现此功能的好方法。

(a == b) | ((a != a) & (b != b))

字符串
这样说(在伪代码中):

a == b or (isnan(a) and isnan(b))


因此,要么a等于b,要么ab都是NaN
如果你有小帧,那么assert_frame_equal就可以了。但是,对于大帧(1000万行),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


(推测)所需单个booltimeit,指示两个DataFrame是否相等:

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

sg2wtvxw

sg2wtvxw3#

喜欢@PhillipCloud的回答,但更多的是写出来的

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

In [27]: df2 = df1.copy()

字符串
它们真的是等价的

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


df 2中不存在于df 1中的nan

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


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

In [38]: df1.fillna(-999) == df1.fillna(-999)
Out[38]: 
      0     1
0  True  True
1  True  True

0h4hbjxa

0h4hbjxa4#

任何使用==与np.NaN的等式比较都是False,即使np.NaN == np.NaN也是False。
简单地说,df1.fillna('NULL') == df2.fillna('NULL'),如果'NULL'不是原始数据中的值。
为了安全起见,请执行以下操作:
示例a)比较具有NaN值的两个 Dataframe

bools = (df1 == df2)
bools[pd.isnull(df1) & pd.isnull(df2)] = True
assert bools.all().all()

字符串
示例B)过滤df 1中与df 2不匹配的行

bools = (df1 != df2)
bools[pd.isnull(df1) & pd.isnull(df2)] = False
df_outlier = df1[bools.all(axis=1)]


(Note:这是错误的- bools[pd.isnull(df 1)== pd.isnull(df 2)] = False)

hwamh0ep

hwamh0ep5#

df.fillna(0) == df2.fillna(0)

字符串
可以使用fillna()Documenation here的数据。

from pandas import DataFrame

# create a dataframe with NaNs
df = DataFrame([{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}])
df2 = df

# comparison fails!
print df == df2

# all is well 
print df.fillna(0) == df2.fillna(0)

8wigbo56

8wigbo566#

从pandas 1.1.0开始就有了df.compare(expect),如果出现任何差异,它会提供详细的结果。

dwbf0jvd

dwbf0jvd7#

米歇尔·德·鲁特尔的答案应该是当前的答案。发布一个答案,因为我没有足够的声誉添加评论。使用数据框架compare方法。
如果dfexpect相等(包括NaN位置),df.compare(expect)将返回空 Dataframe (所有轴均为0长度)。您可以对结果使用empty dataframe属性。

assert(df.compare(expect).empty))

字符串

相关问题