aawwffuullyy
aawwffuullyy

Reputation: 21

Seaborn Heatmap Custom colormap

Hi i just created custom cmap for seaborn heatmap but when i want to use it, it do not show correct color. I've done step by step :

import seaborn as sns
import numpy as np 
import matplotlib
import matplotlib.pyplot as plt

matrix = np.array([[149030, 34],[7442, 12]])
norm = matplotlib.colors.Normalize(matrix.min(), matrix.max())
boundaries = [value for value in matrix.flatten().tolist()]
list.sort(boundaries)

colors = [[norm(boundaries[0]), "#90AFC5"], 
          [norm(boundaries[1]), "#336B87"], 
          [norm(boundaries[2]), "#2a3132"], 
          [norm(boundaries[3]), "#763626"]]
    
    
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)

fig = plt.figure(figsize=(6, 6))
ax = plt.subplot() 
    

annot = np.array([[f"{matrix[0,0]}", f"{matrix[0,1]}"],
                  [f"{matrix[1,0]}", f"{matrix[1,1]}"]], dtype=object)    

sns.heatmap(matrix,
            annot=annot,
            annot_kws={"size": 11},
            fmt="",
            ax=ax,
            vmin=matrix.min(),
            vmax=matrix.max(),
            cmap=cmap,
            cbar=True,
            cbar_kws={'format': '%.0f%%', 'ticks': boundaries, 'drawedges': True},
            xticklabels=False,
            yticklabels=False)

My output as you can see there are two blue columns, but I have defined different colors:

As you can see there is two blue column

Upvotes: 2

Views: 5570

Answers (1)

JohanC
JohanC

Reputation: 80509

If you use a BoundaryNorm, you can give colors for the ranges between the boundaries. To get 4 ranges, you need 5 boundaries. One approach is to add one extra boundary at the end. In the question it is unclear what you want to do with colorvalues that don't coincide with a boundary. In the code below, the color is used for a boundary value and the range up till the next boundary.

import seaborn as sns
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

matrix = np.array([[149030, 34], [7442, 12]])
boundaries = [value for value in matrix.flatten().tolist()]
list.sort(boundaries)
colors = ["#90AFC5", "#336B87", "#2a3132", "#763626"]
norm = matplotlib.colors.BoundaryNorm(boundaries=boundaries + [boundaries[-1]], ncolors=256)

cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)

fig = plt.figure(figsize=(6, 6))
ax = plt.subplot()

annot = np.array([[f"{matrix[0, 0]}", f"{matrix[0, 1]}"],
                  [f"{matrix[1, 0]}", f"{matrix[1, 1]}"]], dtype=object)

sns.heatmap(matrix,
            annot=annot,
            annot_kws={"size": 11},
            fmt="",
            ax=ax,
            cmap=cmap,
            norm=norm,
            cbar=True,
            cbar_kws={'format': '%.0f%%', 'ticks': boundaries, 'drawedges': True},
            xticklabels=False,
            yticklabels=False)
plt.show()

resulting plot

Upvotes: 9

Related Questions