How to express classes along the axis of the heat map in Siborn

I created a very simple heatmap diagram in which Seaborn displays a square similarity matrix. Here is one line of code that I used:

sns.heatmap(sim_mat, linewidths=0, square=True, robust=True) sns.plt.show() 

and this is the result that I get:

enter image description here

What I would like to do is to represent on the x and y axis not the labels of my instances, but a colored indicator (imagine something like a small finger on each axis), where each color represents a different variable associated with each instance (say , I have this information storing a list with the name labels ) plus another legend for this kind of information next to the one that indicates the colors of the lmplot (for example, for lmplot ). It is important that the two information have different color palettes.

Is this possible in Siborn?

UPDATE

What I'm looking for is clustermap as suggested correctly.

 sns.clustermap(sim_mat, row_colors=label_cols, col_colors=label_cols row_cluster=False, col_cluster=False) 

This is what I get btw, the points and lines are too small, and I see no way to increase them in the documentation. I would like to

Plus, how can I add a legend and put it in another position in the same position?

enter image description here

+9
source share
3 answers

There are two options:

First, the heatmap is an indicator of the Axes level, so you can set up the main major axes of the main map for the correlation matrix and flank it using heat maps, which then give you the colors of the class. It will be a bit of work, but gives you a lot of control over how everything works.

This is more or less an option in clustermap , though, so I'm going to demonstrate how to do it here. This is a little hack, but it will work.

First, we upload the sample data and do some roundabout transformations to get the colors for the class labels.

 networks = sns.load_dataset("brain_networks", index_col=0, header=[0, 1, 2]) network_labels = networks.columns.get_level_values("network") network_pal = sns.cubehelix_palette(network_labels.unique().size, light=.9, dark=.1, reverse=True, start=1, rot=-2) network_lut = dict(zip(map(str, network_labels.unique()), network_pal)) network_colors = pd.Series(network_labels).map(network_lut) 

Then we call clustermap to make the main chart.

 g = sns.clustermap(networks.corr(), # Turn off the clustering row_cluster=False, col_cluster=False, # Add colored class labels row_colors=network_colors, col_colors=network_colors, # Make the plot look better when many rows/cols linewidths=0, xticklabels=False, yticklabels=False) 

Side colors are drawn using a heat map, which matplotlib considers quantitative data and, therefore, there is no direct way to get the legend directly from it. Instead, we add an invisible barcode with the correct colors and labels, and then add a legend for this.

 for label in network_labels.unique(): g.ax_col_dendrogram.bar(0, 0, color=network_lut[label], label=label, linewidth=0) g.ax_col_dendrogram.legend(loc="center", ncol=6) 

Finally, move the color bar to take up the empty space where the line dendrogram will usually be, and save the shape.

 g.cax.set_position([.15, .2, .03, .45]) g.savefig("clustermap.png") 

enter image description here

+20
source

Based on the answer above , I think it's worth noting the possibility of using multiple color levels for labels - as noted in the clustermap docs ({row, col} _colors). I could not find an example of several levels, so I decided to share an example here.

 networks = sns.load_dataset("brain_networks", index_col=0, header=[0, 1, 2]) 

network layer

 network_labels = networks.columns.get_level_values("network") network_pal = sns.cubehelix_palette(network_labels.unique().size, light=.9, dark=.1, reverse=True, start=1, rot=-2) network_lut = dict(zip(map(str, network_labels.unique()), network_pal)) 

Create an index using columns for networks

 network_colors = pd.Series(network_labels, index=networks.columns).map(network_lut) 

node level

 node_labels = networks.columns.get_level_values("node") node_pal = sns.cubehelix_palette(node_labels.unique().size) node_lut = dict(zip(map(str, node_labels.unique()), node_pal)) 

Create an index using columns for nodes

 node_colors = pd.Series(node_labels, index=networks.columns).map(node_lut) 

Create a data frame for row and column color levels

 network_node_colors = pd.DataFrame(network_colors).join(pd.DataFrame(node_colors)) 

create clustermap

 g = sns.clustermap(networks.corr(), # Turn off the clustering row_cluster=False, col_cluster=False, # Add colored class labels using data frame created from node and network colors row_colors = network_node_colors, col_colors = network_node_colors, # Make the plot look better when many rows/cols linewidths=0, xticklabels=False, yticklabels=False, center=0, cmap="vlag") 

create two legends - one for each level, creating invisible columns and row columns (as indicated above)

network legend

 for label in network_labels.unique(): g.ax_col_dendrogram.bar(0, 0, color=network_lut[label], label=label, linewidth=0) l1 = g.ax_col_dendrogram.legend(title='Network', loc="center", ncol=5, bbox_to_anchor=(0.47, 0.8), bbox_transform=gcf().transFigure) 

node legend

 for label in node_labels.unique(): g.ax_row_dendrogram.bar(0, 0, color=node_lut[label], label=label, linewidth=0) l2 = g.ax_row_dendrogram.legend(title='Node', loc="center", ncol=2, bbox_to_anchor=(0.8, 0.8), bbox_transform=gcf().transFigure) plt.show() 

enter image description here

+1
source

When both dendrograms are used, you can also add a new hidden axis and draw a legend.

 ax= f.add_axes((0,0,0,0)) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) for label in node_labels.unique(): ax.bar(0, 0, color=node_lut[label], label=label, linewidth=0) l2 = g.ax_row_dendrogram.legend(title='Node', loc="center", ncol=2, bbox_to_anchor=(0.8, 0.8), bbox_transform=f.transFigure) 
0
source

Source: https://habr.com/ru/post/981120/


All Articles