I'd like to make an heatmap featuring both the continuous variable and the categorical data the sample came with. The goal is to have the hue coming from the category and the opacity (or transparency, saturation) from the continuous values.
A toy dataset would be like:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
names = ['Berthe', 'Paul', 'Francis', 'Jane']
time_spent_together = [
[ 1.0, 0.2, 0.7, 0.5 ],
[ 0.2, 1.0, 0.8, 0.5 ],
[ 0.7, 0.8, 1.0, 0.1 ],
[ 0.5, 0.5, 0.1, 1.0 ],
]
type_of_relationship = [
[ 'id', 'friends', 'coworkers', 'nemesis' ],
[ 'friends', 'id', 'family', 'family' ],
[ 'coworkers', 'family', 'id', 'friends' ],
[ 'nemesis', 'family', 'friends', 'id' ],
]
df_times = pd.DataFrame(data=time_spent_together, index=names, columns=names)
df_relationships = pd.DataFrame(data=type_of_relationship, index=names, columns=names)
And the result would 'alter' the discrete plot:
plt.figure(figsize=(3,3))
value_to_int = {j:i for i,j in enumerate(pd.unique(df_relationships.values.ravel()))}
n = len(value_to_int)
cmap = sns.color_palette("tab10", n)
sns.heatmap(df_relationships.replace(value_to_int), cmap=cmap)
With the continuous one
plt.figure(figsize=(3,3))
sns.heatmap(df_times, cmap='Greys',annot=True,
annot_kws={"size": 7}, vmin=0.25, vmax=1)
As you can see, I used seaborn
and pyplot
. I struggle to override the basic behavior. Being able to directly set a cell's color can be the right path ?
Thanks in advance for your answers, Cheers!
Here is an approach using multiple mono-color colormaps, together with a legend:
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
import seaborn as sns
import pandas as pd
import numpy as np
fig, ax = plt.subplots(figsize=(6, 6))
cmaps = ['Blues', 'Oranges', 'Greens', 'Reds', 'Purples']
norm = plt.Normalize(vmin=0.25, vmax=1)
handles = []
for rel, cmap in zip(np.unique(df_relationships.values), cmaps):
sns.heatmap(df_times, mask=df_relationships.values != rel, cmap=cmap, norm=norm, annot=True, cbar=False)
handles.append(plt.Rectangle((0, 0), 0, 0, color=plt.get_cmap(cmap)(0.55), lw=0, label=rel))
plt.colorbar(ScalarMappable(cmap='Greys', norm=norm), ax=ax)
ax.legend(handles=handles, ncol=len(handles), bbox_to_anchor=(0, 1.01), loc='lower left', handlelength=0.7)
plt.tight_layout()
plt.show()