I am trying to make a heatmap with the Seaborn package, where I define my own color ranges. However, I cannot get the legend to show the values in a non-continous way. I would like the following color indication:
0-0.001: green
0.001-0.25: yellow
0.25-0.50: orange
0.50-0.75: red
0.75-1.00: dark red
But I get this:
I suspect that the first range disturbs the picture, because it is smaller. However, I would like the legens "boxes" or area to be the same sizes. Is it therefore possible to have something like this or similar:
The code that I currently use is the one below. Any hint or suggestions would be highly appreciated. Thanks!
my_colors=['#02ab2e','gold','orange','red', 'darkred']
grid_kws = {"height_ratios": (.9, .025), "hspace": .1}
f, (ax, cbar_ax) = plt.subplots(2, gridspec_kw=grid_kws)
ax = sns.heatmap(STEdata.iloc[:,3:13].reindex(ste_order_reg.sort_values().index, axis=0),
yticklabels=2, ax=ax,
cmap = my_colors,
cbar_ax=cbar_ax,
cbar_kws={"orientation": "horizontal"})
# sns.set(rc = {'figure.figsize':(8, 18)})
colorbar = ax.collections[0].colorbar
colorbar.set_ticks([0, 0, 0.25, 0.5, .75])
colorbar.set_ticklabels(['0',']0-0.25]', ']0.25-0.50]',']0.50-0.75]', ']0.75-1.00]'])
CodePudding user response:
To set uneven color ranges, a BoundaryNorm
can be used. The colorbar ticks can be positioned at the center of each range. A ListedColormap
creates a colormap from a list of colors.
import matplotlib.pyplot as plt
from matplotlib.colors import BoundaryNorm, ListedColormap
import seaborn as sns
import numpy as np
my_colors = ['#02ab2e', 'gold', 'orange', 'red', 'darkred']
my_cmap = ListedColormap(my_colors)
bounds = [0, 0.0001, 0.25, 0.50, 0.75, 1]
my_norm = BoundaryNorm(bounds, ncolors=len(my_colors))
grid_kws = {"height_ratios": (.9, .025), "hspace": .1}
fig, (ax, cbar_ax) = plt.subplots(nrows=2, figsize=(8,18), gridspec_kw=grid_kws)
sns.heatmap(np.clip(np.random.rand(21, 12) - 0.1, 0, 1),
yticklabels=2,
ax=ax,
cmap=my_cmap,
norm=my_norm,
cbar_ax=cbar_ax,
cbar_kws={"orientation": "horizontal"})
colorbar = ax.collections[0].colorbar
colorbar.set_ticks([(b0 b1)/2 for b0, b1 in zip(bounds[:-1], bounds[1:])])
colorbar.set_ticklabels(['0', ']0-0.25]', ']0.25-0.50]', ']0.50-0.75]', ']0.75-1.00]'])
plt.show()
Instead of a colormap, a custom legend could be created. The same BoundaryNorm
will be needed to assign the correct colors in the heatmap. ax.text()
and ax.hlines()
can be used to place text and lines for the grouping. The