Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

MAX value in dash table (@app.callback)

Hi there,
I want to render a dash table that updates itself each second which perfectly works.
Besides that, I have found this amazing feature to highlight certain values (please refer to: https://dash.plot.ly/datatable/style - Conditional formatting - highlighting cells).

Is there someone who could help me to apply it on my use case:

This is my test data set (json format):
[
{
“A”: “angry”,
“Percentage”: 120
},
{
“A”: “sad”,
“Percentage”: 12.4
},
{
“A”: “happy”,
“Percentage”: 1.5
},
{
“A”: “bored”,
“Percentage”: 99
}
]

and my function looks like:
@app.callback(Output(‘resulttable2’,‘children’),
[Input(‘interval-component’,‘n_intervals’)])
def generate_table2(max_rows=10):
df = pd.read_json(‘test.json’)
arr=np.array(df[“Percentage”], dtype=float)
arr2 = np.int64(arr)
maxvalue = max(arr2)
return dash_table.DataTable(
id=‘table’,
columns=[{“name”: i, “id”: i} for i in df.columns],
data=df.to_dict(‘records’),
style_data_conditional=[
{
‘if’: {
‘column_id’: ‘Percentage’,
‘filter_query’: ‘{Percentage} > maxvalue’
},
‘backgroundColor’: ‘#3D9970’,
‘color’: ‘green’,
},
]
)

If I replace maxvalue (‘filter_query’: ‘{Percentage} > maxvalue’) by a figure such as 4, it perfectly works, but I would like to highlight the max value of the whole column to make it flexible. In this case 120.

Looking forward to your feedback.
Thank you very much in advance

@plotlynewbie

There’s currently no support for highlighting the max value automatically through some filter_query syntax.

What you can do is define a callback on data with style_data_conditional as state and look for the highest value in the column you want and update the style_data_conditional prop accordingly.

My Python is a bit :potato: but something like this:

import re

import dash
from dash.dependencies import Input, Output, State

from dash_table import DataTable
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    DataTable(
        id='table',
        columns=[{
            'name': x,
            'id': x,
            'type': 'text' if x=='A' else 'numeric'
        } for x in ['A', 'Percentage']],
        editable=True,
        style_data_conditional=[{
            'if': {
                'filter_query': '{Percentage} gt 50'
            },
            'backgroundColor': 'lightgrey'
        }],
        data=[
            dict(A='angry', Percentage=120),
            dict(A='sad', Percentage=12.4),
            dict(A='happy', Percentage=1.5),
            dict(A='bored', Percentage=99)
        ]
    )
])

@app.callback(
    [Output('table', 'style_data_conditional')],
    [Input('table', 'data')],
    [State('table', 'style_data_conditional')]
)
def updateStyles(data, styles):
    max_value = max(data, key=lambda datum: datum.get('Percentage'))

    styles = list(filter(lambda style:
        style.get('if') is None or
        style.get('if').get('filter_query') is None or
        re.match('[{]Percentage[}]\seq\s\d+', style.get('if').get('filter_query')) is None
    , styles))

    styles.append({
        'if': {
            'filter_query': '{{{}}} eq {}'.format('Percentage', max_value.get('Percentage'))
        },
        'backgroundColor': 'lightblue'
    })

    return styles,


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

Since you are already updating the data with an interval, you might want to take advantage of multiple output callbacks and update both the data and the styles in a single callback if possible.