Dash table - highlight cell(s) with different value than in previous row

Hi,

I am trying to write a code to highlight the cells that have a different value in comparison to the preceding row in dash or ag-grid table.

Inside a large callback I tried the following without success:

    styles = []
    for i in range(1, len(df)):
        prev_row = df.iloc[i-1]
        curr_row = df.iloc[i]

        # Compare values in each column
        for col in df.columns:
            if curr_row[col] != prev_row[col]:
                styles.append({
                    'if': {
                        'filter_query': f'index = {i} and column_id = "{col}"',
                    },
                    'backgroundColor': '#FF4136',
                    'color': 'white'
                })
    
    method_table = dash_table.DataTable(
        data=df.to_dict("records"),
        columns=[{"name": i, "id": i} for i in df.columns],
        style_data_conditional=styles,
        style_header={'backgroundColor': 'rgb(44, 62, 80)', 'color': 'white'}
    )

Any suggestions would be appreciated.

I think you can find different between rows in pandas first then use this to style your dash datatable. Below is my sample code:

from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
import numpy as np
import dash_bootstrap_components as dbc
from dash import Dash, dash_table
import numpy as np
data = OrderedDict(
    [("col1", [3, 1,2]),
     ("col2", [3, 3, 1]),
     ("col3", [1, 3, 3]),
    ])

df = pd.DataFrame(data)

# Find different between rows
df['col_1_shift'] = df['col1'] - df['col1'].shift(-1)
df['col_2_shift'] = df['col2'] - df['col2'].shift(-1) 
df['col_3_shift'] = df['col3'] - df['col3'].shift(-1) 
df.fillna(0,inplace=True)

app = Dash(__name__, external_stylesheets=[dbc.themes.LUX])


#print(df)
app.layout = dash_table.DataTable(
    data=df.to_dict('records'),
    
    #sort_action='native',
    columns=[{'name': i, 'id': i} for i in df.columns[0:3]],
    style_data_conditional=[
        {'if': {'filter_query': '{col_1_shift} > 0',
                'column_id': 'col1'
            },
            'color': 'white','backgroundColor':'green'
        },
                {'if': {'filter_query': '{col_1_shift} < 0',
                'column_id': 'col1'
            },
            'color': 'white','backgroundColor':'red'
        },
                {'if': {'filter_query': '{col_2_shift} > 0',
                'column_id': 'col2'
            },
            'color': 'white','backgroundColor':'green'
        },
                {'if': {'filter_query': '{col_2_shift} < 0',
                'column_id': 'col2'
            },
            'color': 'white','backgroundColor':'red'
        },
                {'if': {'filter_query': '{col_3_shift} > 0',
                'column_id': 'col3'
            },
            'color': 'white','backgroundColor':'green'
        },
                {'if': {'filter_query': '{col_3_shift} < 0',
                'column_id': 'col3'
            },
            'color': 'white','backgroundColor':'red'
        },
        
    ] 
)

if __name__ == '__main__':
    app.run_server(debug=False)

Hope this help.

1 Like

Hey. Thanks! This solved it for numeric values. For string ones I am using:

df['col_4_shift'] = df['col4'] != df['col4'].shift(-1) 

which returns Boolean. I am then highlighting True cells.

This is fine. However, it also returns True for first row value even though there is nothing to really compare it too. So the string cells in first row are always highlighted.

I think you can use df.at to change value of this cell.
In your case you could use df.at[0,'col_4_shift'] = 'False'

Maybe it should help.