Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Plotly Annotated Heatmap Colorscale (DASH)

Hi all,
Using the ff.annotated heatmap in DASH.

Does anyone know how to make a custom colorscale so the negative numbers in their heatmap are Red and the positive ones are green? and maybe even put the numbers close to 0 at yellow?

Thank you

Just bumping this thread if anyone has a solution. Thanks

Hi @np162629

Colors in the heat map are assigned based on the values of z normalized between 0 and 1.
You can then set discrete colors based on certain ranges in this normalized scale.

The challenge is how to identify the negative numbers when they have been normalized between 0 and 1.

Here is one solution:


import numpy as np
np.random.seed(1)

z  = np.random.randint(low=-20, high=100, size=(10, 10))

# get a flattened array of all of the z values, sorted
z_flat = np.sort(z, axis=None) 

#  find how many negative numers are in the array
negative_numbers = np.sum(np.array(z_flat) <= 0, axis=0)

# normalize array between 0 and 1 for the color scale
def normalize(x):
    return (x - np.min(x)) / (np.max(x) - np.min(x))
normalized_scale = normalize(z_flat)


# find the point in the normalized scale where the numbers change from neg to positive
border1 = normalized_scale[negative_numbers]

#  set the second border to be "close" to zero
border2 = border1 * 1.1

# custom color scale
mycolors=[[0, 'red'],        
        [border1, 'red'],
        [border1, 'yellow'], 
        [border2, 'yellow'],
        [border2, 'green'], 
        [1, 'green']]


fig = ff.create_annotated_heatmap(z=z, colorscale=mycolors)

1 Like

also ICYMI there are lots of examples with how to do this with the dash_table as well: https://dash.plotly.com/datatable/conditional-formatting

Right! I forgot about that - using a dash table would be way easier :blush:

Thanks everyone! Went with the dash_table option, it was very easy!

If I wanted to separate the numbers by negatives and positives by column, I found this relevant example in the conditional formatting section:

app.layout = dash_table.DataTable(
data=df.to_dict(‘records’),
sort_action=‘native’,
columns=[{‘name’: i, ‘id’: i} for i in df.columns],
style_data_conditional=(
[
{
‘if’: {
‘filter_query’: ‘{{{}}} > {}’.format(col, value),
‘column_id’: col
},
‘backgroundColor’: ‘#3D9970’,
‘color’: ‘white’
} for (col, value) in df.quantile(0.1).iteritems()
] +
[
{
‘if’: {
‘filter_query’: ‘{{{}}} <= {}’.format(col, value),
‘column_id’: col
},
‘backgroundColor’: ‘#FF4136’,
‘color’: ‘white’
} for (col, value) in df.quantile(0.5).iteritems()
]
)
)

What would I change the last lines in each block of code to for the formatting to be below 0 and above 0?

Line 1 (want this to be above 0): “} for (col, value) in df.quantile(0.1).iteritems()”
Line 2 (want this to be below 0): “} for (col, value) in df.quantile(0.5).iteritems()”

Sorry I am a bit of a novice :slight_smile:

Hey @np162629 Try this:

app.layout = dash_table.DataTable(
    data=df.to_dict('records'),
    sort_action='native',
    columns=[{'name': i, 'id': i} for i in df.columns],
    style_data_conditional=[
        {
            'if': {
                'filter_query': '{{{col}}} < 0'.format(col=col),
                'column_id': col
            },
            'backgroundColor': 'red',  
            'color': 'white'
        } for col in df.columns
    ]
    +[
        {
            'if': {
                'filter_query': '{{{col}}} >= 0'.format(col=col),
                'column_id': col
            },
            'backgroundColor': 'green', 
            'color': 'white'
        } for col in df.columns
    ]
)

That worked. Thanks for all the help!