我有一个函数的简单测试用例,它返回一个可能包含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
但是,由于NaN,我不能简单地依赖==
运算符。我的印象是,解决这个问题的合适方法是使用equals方法。来自documentation:
pandas.DataFrame.equals
DataFrame.equals(other)
Determines if two NDFrame objects contain the same elements. NaNs in the same location are considered equal.
尽管如此:
>>> expected.equals(log_events)
Out[4]: False
一点点挖掘就会发现框架的差异:
>>> 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
强制输出浮点块为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()
然而,它没有。我的想法是错的,还是Pandas API中的不一致?考虑到可能存在NaN,我应该为我的目的进行什么测试?
答案 0 :(得分:4)
.equals()
正如它所说的那样。它测试元素之间的确切相等性,nans(和NaTs)的定位,dtype相等性和索引相等性。可以将其视为df is df2
类型的测试,但它们不必实际上是同一个对象,IOW,df.equals(df.copy())
始终为True。
您的示例失败,因为不同的dtypes不相等(尽管它们可能相同)。因此,您可以使用com.array_equivalent
来实现此目的,或(df == df2).all().all()
如果您没有nans
。
这是np.array_equal
的替代品,因为纳米位置检测(和对象dtypes)而被破坏。
它主要在内部使用。也就是说,如果你喜欢等价的增强(例如,==
意义上的元素是等价的,并且nan
位置匹配),请在github上打开一个问题。 (甚至更好地提交公关!)
答案 1 :(得分:0)
我使用一种变通方法来研究(s/conform ::b '(foo (:x 1 :y 2)))
实例:
MagicMock