Custom Colormap. How to specify coloraa

Hi all, I have created the following heatmap using Plotly Graphic objects and figure factory in Python using the plotly library.

I want to use a custom color map to color the cells dependant on their location. i.e bottom left is 1 x 1 should be rgb(146, 208,80) and top right , rgb(204, 0, 0).

The complete color range is below along with the values each cell value.
(i.e impact of 1 x likelihood of 1 = 1 = Very Low
impact of 5 x likelihood of 5 = 25 = Very High

Impact Matrix Colours

Values RGB Hex
Very High 20 - 25 204, 0, 0 #CC0000
High 12 - 16 255, 51, 0 #FF3300
Medium 8 - 10 255, 192, 0 #FFCC00
Low 4 - 6 0, 176, 80 #00B05
Very Low 1-3 146, 208, 80 #92D050

This should map like the following

I have the following code to create the above heatmap

# Create our temp dataframe df and pull in the data we are interested in.
# We also use this opertunity to remove blank entries
df = raca_df[['risk_id', 'gross_impact','gross_likelihood', 'business_unit', 'net_impact', 'net_likelihood']].dropna()

# loop through our columns and set the type accordingly. 
# Here we set it to int to prevent us getting the following error
# "IndexError: arrays used as indices must be of integer (or boolean) type"
for item in ['gross_impact','gross_likelihood','net_impact', 'net_likelihood']:
    df[item] = df[item].astype('int')

# get our counts of the gross number of impact,likelihood pair
gc = df.groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values


# # Set up a blank 5 x 5 array and fill with zeros
# # The line below was from teh original stackoverflow solution but it would fail
# # us if we only had an impact of 4 our matrix would not size to 5 x 5 hence our line
# # beneath it
# #heatmap = np.zeros((np.max(df['gross_impact']), np.max(df['gross_likelihood'])))
heatmap_g = np.zeros((np.max(5), np.max(5)),dtype=int)

# # Map the counts to our matrix
# # the -1 makes python coung from 1 not 0. 
heatmap_g[gc[:,1]-1, gc[:,0]-1] = gc[:,2]

# Set up my Axis labels
x=['Minor [Very Low]<br>1', 'Important [Low]<br>2', 'Significant [Moderate]<br>3', 'Major [High]<br>4', 'Critical [Very High]<br>5']
y=['Very Remote<br>1', 'Remote<br>2', 'Unlikely<br>3', 'Possible<br>4', 'Highly Possible<br>5']

z_text = np.around(heatmap_g, decimals=0)# Only show rounded value (full value on hover)

fig = ff.create_annotated_heatmap(heatmap_g, x=x, y=y, colorscale='Blues')

# Set the axes lables from the bottom. Eases readability
fig['layout']['xaxis']['side'] = 'bottom'

#fig.update_traces({'int': 0}, selector=dict(type='heatmap'))
fig.layout.update({'title': "Risk Matrix"}, title_x=0.5)
fig.layout.update({'xaxis_title': "Impact"})
fig.layout.update({'yaxis_title': "Likelihood"})
fig.show()

Having read around the manuals ewtc and tried various incantations of these I am still unable to create a custom colorscale that will map the colours to the matrix. Ignore the numbered annotation in thee cell that’s just the size of the data that hots that value.

Can anyone show me how to use a custom color map in my example?

Hi @twelsh37

You could try using a DataTable with conditional formatting. (I think it’s an easier way). Conditional Formatting | Dash for Python Documentation | Plotly

See the example called: “Highlighting cells by value with a colorscale like a heatmap”

Hi @AnnMarieW

Thanks for teh advice. I had tried that earlier but the output is not as nice as a plotly heat map. :frowning: This is to go into a report so bells and whistles baffle the higherups.

Hi @twelsh37

Using the conditional format will be like your example, what other nice thing you want?
I use that in my app

Can you post what you have tried so far? From the docs, it seems that you can simply pass your own colorscale,

colorscale=[[0, "rgb(166,206,227)"],
                [0.25, "rgb(31,120,180)"],
                [0.45, "rgb(178,223,138)"],
                [0.65, "rgb(51,160,44)"],
                [0.85, "rgb(251,154,153)"],
                [1, "rgb(227,26,28)"]]

Thanks. THat was helpful. Not quite what I’m looking for but moving me closer.

@twelsh37

A search on this forum, for discrete colorscale displays a lot of examples I posted during the last years.
Here
https://community.plotly.com/t/what-is-wrong-with-this-example/30771/4
or here:
https://chart-studio.plotly.com/~empet/15229/heatmap-with-a-discrete-colorscale/#/
it is explained how you can define a discrete colorscale. In your case the normalization function is:

f: [1, 25]->[0,1]
f(t) = (t-1)/24

Hence:

f(1) = 0
f(4) = 1/8
f(8) = 7/24
f(12) = 11/24
f(20) = 19/24
f(25) = 1

Your intervals are not adjacent, but I think that 7, 11, 17, 18, 19 cannot be met among your data. If this is the case then
the corresponding colorscale is defined as follows:

dcolorscale= [[0, '#92D050'],
             [1/8, '#92D050'],
             [1/8, '#00B005'],
             [7/24, '#00B005'],
             [7/24, '#FFCC00'],
             [11/24, '#FFCC00'],
             [11/24, '#FF3300'],
             [19/24, '#FF3300'],
             [19/24, '#CC0000'],
             [1, '#CC0000']]