pandas.DataFrame.equals的合同

jwi*_*ner 7 python pandas

我有一个函数的简单测试用例,它返回一个可能包含NaN的df.我正在测试输出和预期输出是否相等.

>>> output
Out[1]: 
      r   t  ts  tt  ttct
0  2048  30   0  90     1
1  4096  90   1  30     1
2     0  70   2  65     1

[3 rows x 5 columns]
>>> expected
Out[2]: 
      r   t  ts  tt  ttct
0  2048  30   0  90     1
1  4096  90   1  30     1
2     0  70   2  65     1

[3 rows x 5 columns]
>>> output == expected
Out[3]: 
      r     t    ts    tt  ttct
0  True  True  True  True  True
1  True  True  True  True  True
2  True  True  True  True  True
Run Code Online (Sandbox Code Playgroud)

但是,==由于NaNs ,我不能简单地依赖运营商.我的印象是,解决这个问题的合适方法是使用equals方法.从文档:

pandas.DataFrame.equals
DataFrame.equals(other)
Determines if two NDFrame objects contain the same elements. NaNs in the same location are considered equal.
Run Code Online (Sandbox Code Playgroud)

但是:

>>> expected.equals(log_events)
Out[4]: False
Run Code Online (Sandbox Code Playgroud)

一点点挖掘揭示了框架的差异:

>>> output._data
Out[5]: 
BlockManager
Items: Index([u'r', u't', u'ts', u'tt', u'ttct'], dtype='object')
Axis 1: Int64Index([0, 1, 2], dtype='int64')
FloatBlock: [r], 1 x 3, dtype: float64
IntBlock: [t, ts, tt, ttct], 4 x 3, dtype: int64
>>> expected._data
Out[6]: 
BlockManager
Items: Index([u'r', u't', u'ts', u'tt', u'ttct'], dtype='object')
Axis 1: Int64Index([0, 1, 2], dtype='int64')
IntBlock: [r, t, ts, tt, ttct], 5 x 3, dtype: int64
Run Code Online (Sandbox Code Playgroud)

强制将浮动块输出到int,或强制预期的int块浮动,并且测试通过.

显然,存在不同的平等意义,并且DataFrame.equals在某些情况下执行的那种测试可能是有用的.尽管如此,之间的差距==,并DataFrame.equals是令人沮丧的我,似乎是一个矛盾.在伪代码中,我希望它的行为匹配:

(self.index == other.index).all() \
and (self.columns == other.columns).all() \
and (self.values.fillna(SOME_MAGICAL_VALUE) == other.values.fillna(SOME_MAGICAL_VALUE)).all().all()
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.我的想法是错的,还是Pandas API中的不一致?考虑到可能存在NaN,我应该为我的目的进行什么测试呢?

Jef*_*eff 5

.equals()照着说的去做。它测试元素之间的精确相等性,nan(和NaT)的位置,dtype相等性和索引相等性。可以将其视为df is df2测试的类型,但实际上它们不必是同一对象,IOW df.equals(df.copy())始终为True。

您的示例失败,因为不同的dtype不相等(尽管它们可能等效)。因此,您可以使用com.array_equivalent它,或者(df == df2).all().all()如果没有的话nans

这是一个替换,np.array_equal对于nan位置检测(和对象dtypes)而言,该替换是无效的。

它主要在内部使用。也就是说,如果您喜欢对等的增强功能(例如,元素在==意义上和nan位置匹配方面是等效的),请在github上发布一个问题。(甚至最好提交一份公关!)