Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign a color to a specific value on a heatmap

I am making a heatmap in seaborn. I am using 'viridis', but I modify it slightly so some of the values get particular colors. In my MWE, .set_over is used to set the values above 90 to 'black', and .set_under is used to set the values below 10 to 'white'. I also mask out part of the heatmap. This all works fine.

How can I also map a middle range value, 20, to 'orange', and without effecting the current colorbar appearance? As you can see, .set_over, and .set_under do not change the colorbar appearance.

import matplotlib
import seaborn as sns
import numpy as np
np.random.seed(7)
A = np.random.randint(0,100, size=(20,20))
mask_array = np.zeros((20, 20), dtype=bool)
mask_array[:, :5] = True
cmap = matplotlib.colormaps["viridis"]
# Set the under color to white
cmap.set_under("white")
# Set the voer color to white
cmap.set_over("black")
# Set the background color

g = sns.heatmap(A, vmin=10, vmax=90, cmap=cmap, mask=mask_array)
# Set color of masked region
g.set_facecolor('lightgrey')

enter image description here

I have seen Map value to specific color in seaborn heatmap, but I am not sure how I can use it to solve my problem.

like image 958
graffe Avatar asked Feb 04 '26 04:02

graffe


1 Answers

Consider the following:

import matplotlib as mpl
import seaborn as sns
import numpy as np

A = np.random.randint(0,100, size=(20,20))
mask_array = np.zeros((20, 20), dtype=bool)
mask_array[:, :5] = True
cmap = mpl.colormaps["viridis"]

newcolors = cmap(np.linspace(0, 1, 100))
newcolors[:10] = np.array([1,1,1,1])
newcolors[90:] = np.array([0,0,0,1])
newcolors[20] = mpl.colors.to_rgb('tab:orange') + (1,)

newcmap = mpl.colors.ListedColormap(newcolors)

g = sns.heatmap(A, cmap=newcmap, mask=mask_array)
# Set color of masked region
g.set_facecolor('lightgrey')

Sample result:

enter image description here

The following (appended to the above script) will make it so that the colorbar has a visible outline.

cbar_ax = g.figure.axes[-1]

for spine in cbar_ax.spines.values():
    spine.set(visible=True)

Sample result with outline:

enter image description here


In order to mask the colors of the heatmap, but not show an updated colorbar, set cbar=False, and then attach a custom colorbar, as shown in Standalone colorbar.

g = sns.heatmap(A, cmap=newcmap, mask=mask_array, cbar=False)

# add a new axes of the desired shape
cb = g.figure.add_axes([0.93, 0.11, 0.025, 0.77])

# attach a new colorbar to the axes
mpl.colorbar.ColorbarBase(cb, cmap='viridis', norm=mpl.colors.Normalize(10, 90),  # vmax and vmin
                          label=None, ticks=range(10, 91, 10))

enter image description here

like image 55
Ben Grossmann Avatar answered Feb 05 '26 18:02

Ben Grossmann