I want to plot the p-value in a heatmap. I am thus interested in the 1%, 5% and 10% steps. My goal is to plot 3 colors for the before mentioned steps and number that are greater than 0.1 are colored in white.
This is what I have come up with so far:
Is there a way to have a completely custom legend/bar at the bottom divided into 4 equally large fields of the 3 blue colors and white:
My code:
Granger2.columns = Granger_colnames
Granger2.index = Granger_rownames
cbar_ticks = [0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]
fig, ax = plt.subplots(figsize=(6,25))
sns.heatmap(Granger2, cmap=rvb, cbar=True, ax=ax,linewidths=.5,vmin=0,cbar_kws={"orientation": "horizontal", "pad":0.01,"ticks": cbar_ticks})
ax.xaxis.tick_top() # x axis on top
ax.xaxis.set_label_position('top')
#Remove ticks
ax.tick_params(axis='both', which='both', length=0)
# Drawing the frame
ax.axhline(y = 0, color='k',linewidth = 1)
ax.axhline(y = Granger2.shape[0], color = 'k',linewidth = 1)
ax.axvline(x = 0, color = 'k', linewidth = 1)
ax.axvline(x = Granger2.shape[1], color = 'k', linewidth = 1)
cbar = ax.collections[0].colorbar
cbar.ax.axhline(y = 0, color='k',linewidth = 1)
cbar.ax.axhline(y = 1, color = 'k',linewidth = 1)
cbar.ax.axvline(x = 0, color = 'k', linewidth = 1)
cbar.ax.axvline(x = 1, color = 'k', linewidth = 1)
cbar.ax.tick_params(axis='both', which='both', length=0)
plt.show()
CodePudding user response:
You could use a ListedColormap
for the colors, and a BoundaryNorm
to set custom boundaries:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm
import numpy as np
bounds = [0, .01, .05, .10, 1]
norm = BoundaryNorm(bounds, ncolors=len(bounds) - 1)
cmap = ListedColormap(['#084a91', '#4a98c9', '#b7d4ea', 'white'])
fig, ax = plt.subplots(figsize=(6, 7))
sns.heatmap(np.random.rand(20, 20), cmap=cmap, norm=norm, cbar=True,
linewidths=.5, linecolor='lightgrey', clip_on=False,
cbar_kws={"orientation": "horizontal", "pad": .01}, ax=ax)
ax.xaxis.tick_top()
ax.tick_params(axis="both", length=0) # hide ticks
for spine in fig.axes[-1].spines.values():
spine.set(visible=True, lw=.5, edgecolor="grey") # show outline
plt.tight_layout()
plt.show()
CodePudding user response:
Step 1:
Transform the Granger2
and redefine it with its range of values using the between
function of pandas:
for col in Granger_colnames:
Granger2.loc[Granger2[col].between(0,0.01), col] = 100
Granger2.loc[Granger2[col].between(0.01,0.05), col] = 200
Granger2.loc[Granger2[col].between(0.05,0.1), col] = 300
Granger2.loc[Granger2[col].between(0.1,1), col] = 400
I pick {100,200,300,400}
but you can pick other values.
Step 2:
Apply a new colorscheme to colorbar based on {100,200,300,400}
, include this definition in cmap
.
Step 3:
Relabel the colorbar with cbar.set_ticklabels(['0.00', '0.01', '0.05', '0.1', '1.00'])
.
Example:
Then the collowing code with application to a random matrix should work:
# Granger2.columns = Granger_colnames =
# Granger2.index = Granger_rownames
import pandas as pd
from random import choice
from string import ascii_lowercase, digits
import seaborn as sns
chars = ascii_lowercase digits
Granger_rownames = [''.join(choice(chars) for _ in range(3)) for _ in range(10)]
Granger_colnames = [''.join(choice(chars) for _ in range(3)) for _ in range(10)]
cbar_ticks = [0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]
Granger2 = np.random.rand(10, 10)
Granger2 = pd.DataFrame(Granger2, index = Granger_rownames, columns = Granger_colnames)
#create a mask for Granger2 and change it to {100,200,300,400}
for col in Granger_colnames:
Granger2.loc[Granger2[col].between(0,0.01), col] = 100
Granger2.loc[Granger2[col].between(0.01,0.05), col] = 200
Granger2.loc[Granger2[col].between(0.05,0.1), col] = 300
Granger2.loc[Granger2[col].between(0.1,1), col] = 400
dataFrame = Granger2
myColors = ((15/256,82/256,186/256, 1), (101/256,147/256,245/256, 1), (220/256, 230/256, 250/256, 1), (1, 1, 1, 1))
cmap = LinearSegmentedColormap.from_list('Custom', myColors, len(myColors))
fig, ax = plt.subplots(figsize=(6,6))
ax = sns.heatmap(dataFrame, cmap=cmap, linewidths=1, linecolor='black', cbar_kws={"orientation": "horizontal", "pad":0.01,"ticks": cbar_ticks})
ax.xaxis.tick_top() # x axis on top
ax.xaxis.set_label_position('top')
# Manually specify colorbar and change the label
cbar = ax.collections[0].colorbar
cbar.set_ticks([100, 175, 250, 325, 400])
cbar.set_ticklabels(['0.00', '0.01', '0.05', '0.1', '1.00'])
ax.axhline(y=0, color='k',linewidth=1)
ax.axhline(y=dataFrame.shape[1], color='k',linewidth=1)
ax.axvline(x=0, color='k',linewidth=1)
ax.axvline(x=dataFrame.shape[0], color='k',linewidth=1)
plt.show()