13

I am attempting to compare two DataFrames with pandas testing assert_frame_equal. These frames contain floats that I want to compare to some user defined precision.

The check_less_precise argument from assert_frame_equal seems to suggest that I can specify the number of digits after the decimal point to compare. To quote the API Reference page -

check_less_precise: Specify comparison precision. Only used when check_exact is False. 5 digits (False) or 3 digits (True) after decimal points are compared. If int, then specify the digits to compare

API Reference

However, This doesn't seem to work when the floats are less than 1.

This raises an AssertionError

import pandas as pd

expected = pd.DataFrame([{"col": 0.1}])
output = pd.DataFrame([{"col": 0.12}])
pd.testing.assert_frame_equal(expected, output, check_less_precise=1)

while this does not

expected = pd.DataFrame([{"col": 1.1}])
output = pd.DataFrame([{"col": 1.12}])
pd.testing.assert_frame_equal(expected, output, check_less_precise=1)

can someone help explain this behavior, is this a bug?

0

1 Answer 1

10

check_less_precise works more like relative tolerance. See details below.

I dug through the source code and found out what is happening. Eventually the function decimal_almost_equal gets called which looks like this in normal Python (its in Cython).

def decimal_almost_equal(desired, actual, decimal):
    return abs(desired - actual) < (0.5 * 10.0 ** -decimal)

See the source code here Here is actual call to the function:

decimal_almost_equal(1, fb / fa, decimal)

Where in this example

fa = .1
fb = .12
decimal = 1

So the function call becomes

decimal_almost_equal(1, 1.2, 1)

Which decimal_almost_equal evaluates as

abs(1 - 1.2) < .5  * 10 ** -1

Or

.2 < .05

Which is False.

So the comparison is based on percentage difference and not total difference it seems.

If you want an absolute comparison, check out np.allclose.

np.allclose(expected, output, atol=.1)
True
Sign up to request clarification or add additional context in comments.

4 Comments

So your not going to have much luck comparing anything to fa = 0.0
I think it takes a different path for 0. There is much more to the story than this little snippet.
Thanks Ted, I started to thinking that I'm blind or something, trying to figure out why I'm getting assertion errors although they shouldn't appear...
I was confused by decimal_almost_equal, which seemed like an absolute tolerance, but upon closer inspection, the call decimal_almost_equal(1, fb / fa, decimal) is really relative tolerance! Just want to make this note here in case others may be confused as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.