Override default True == 1, False == 0 behavior

123 views Asked by At

I have dataframes that can contain a mix of booleans and integers, and I'd like to be able to do things like df_1 == df_2.loc[0,0], and guarantee that if df_2.loc[0,0] is 1 that it won't match True values in df_1.

2

There are 2 answers

0
OCa On

Pre-processing your data to avoid collisions between varied datatypes is better practice. But assuming you cannot separate integers from booleans in your dataframes, then enhance == with boolean detection:

def BoolProofCompare(a, b):
    '''Override default True == 1, False == 0 behavior'''
    return a==b and isinstance(a, bool)==isinstance(b, bool)

BoolProofCompare(1, True)  # False
BoolProofCompare(0, False)  # False
BoolProofCompare(1, 1)  # True
BoolProofCompare(False, False)  # True
# and so on and so forth

Now, I gather that what you request is cell by cell comparison of a single value, e.g. df_2[0][0], with each element in a dataframe, e.g. df_1, with True==1 and False==0 equalities disabled. In that case, use applymap to broadcast the above comparison to every cell:

# my example of input dataframe
df
    col1  col2
0   True     1
1      1     2
2  False     3
3      0     4

df.applymap(lambda x : BoolProofCompare(x, True))
    col1   col2
0   True  False
1  False  False
2  False  False
3  False  False

df.applymap(lambda x : BoolProofCompare(x, False))
    col1   col2
0  False  False
1  False  False
2   True  False
3  False  False

df.applymap(lambda x : BoolProofCompare(x, 1))
    col1   col2
0  False   True
1   True  False
2  False  False
3  False  False

df.applymap(lambda x : BoolProofCompare(x, 0))
    col1   col2
0  False  False
1  False  False
2  False  False
3   True  False

I suppose it would be more convenient to encapsulate the enhanced comparison inside a new function, like this:

def BoolProofCompare_df(df, a):
    '''
    Compare single value *a* with dataframe *df*, cell by cell, 
    with True==1 and False==0 equalities disabled.
    '''
    return df.applymap(lambda x : BoolProofCompare(x, a))
0
pts On

See @OCa's answer for the BoolProofCompare function. An alternative implementation which also makes 0 (int) different from 0.0 (float):

def BoolProofCompare(a, b):
    return a == b and type(a) == type(b)

The reason why just return a == b doesn't work is that in Python True == 1 and True == 1.0.