title: contract of pandas.DataFrame.equals
body: <p>I have a simple test case of a function which returns a df that can potentially contain NaN. I was testing if the output and expected output were equal.</p>
  
  <pre><code>&gt;&gt;&gt; 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]
  &gt;&gt;&gt; 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]
  &gt;&gt;&gt; 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
  </code></pre>
  
  <p>However, I can't simply rely on the <code>==</code> operator because of NaNs. I was under the impression that the appropriate way to resolve this was by using the equals method. From the <a href="http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.equals.html" rel="noreferrer">documentation</a>:</p>
  
  <pre><code>pandas.DataFrame.equals
  DataFrame.equals(other)
  Determines if two NDFrame objects contain the same elements. NaNs in the same location are considered equal.
  </code></pre>
  
  <p>Nonetheless:</p>
  
  <pre><code>&gt;&gt;&gt; expected.equals(log_events)
  Out[4]: False
  </code></pre>
  
  <p>A little digging around reveals the difference in the frames: </p>
  
  <pre><code>&gt;&gt;&gt; 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
  &gt;&gt;&gt; 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
  </code></pre>
  
  <p>Force that output float block to int, or force the expected int block to float, and the test passes.</p>
  
  <p>Obviously, there are different senses of equality, and the sort of test that <code>DataFrame.equals</code> performs could be useful in some cases. Nonetheless, the disparity between <code>==</code> and <code>DataFrame.equals</code> is frustrating to me and seems like an inconsistency. In pseudo-code, I would expect its behavior to match:</p>
  
  <pre><code>(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()
  </code></pre>
  
  <p>However, it doesn't. Am I wrong in my thinking, or is this an inconsistency in the Pandas API? Moreover, what IS the test I should be performing for my purposes, given the possible presence of NaN?</p>