Search code examples
pythonpandaspandas-stylespython-applymap

Pandas conditional formatting: Highlighting cells in one frame that are unequal to those in another


Given two pandas dataframes df1 and df2 that have exact same schema (i.e. same index and columns, and hence equal size), I want to color just those cells in df1 that are unequal to their counterpart in df2. Any hints?

More generally, if I have a predefined matrix of colors, colormat, that has the same dimensions as df1, can I somehow color each cell of df1 based on the color given in colormat?

Simple example

df1 = pd.DataFrame({'colA':[3,4,5], 'colB':[6,7,8]})
df2 = pd.DataFrame({'colA':[3,4,50], 'colB':[6,70,8]})

colormat = df1.eq(df2).replace({False:'red', True:'green'})

When applied to df1, I want df1.loc[2,'colA'] and df1.loc[1, 'colB'] to be colored red, and the other cells green, since 5 != 50 and 7 != 70


Solution

  • The styles need to be valid CSS, so change 'red' and 'green' to 'background-color: red' and 'background-color: green', then simply apply on axis=None and pass the colormat DataFrame:

    import pandas as pd
    
    df1 = pd.DataFrame({'colA': [3, 4, 5], 'colB': [6, 7, 8]})
    df2 = pd.DataFrame({'colA': [3, 4, 50], 'colB': [6, 70, 8]})
    
    colormat = df1.eq(df2).replace({False: 'background-color: red',
                                    True: 'background-color: green'})
    df1.style.apply(lambda _: colormat, axis=None)
    

    Depending on size of the DataFrames np.where may be more performant:

    colormat = np.where(df1.eq(df2),
                        'background-color: green',
                        'background-color: red')
    
    df1.style.apply(lambda _: colormat, axis=None)
    

    Both Produce:

    styled table