0

I am using seaborn.clustermap to create an ordered heatmap. I would like to be able to save both of the dendrograms and the heatmap separately. Is there a way to separate the three.

My code for creating the heatmap/dendrogram combination is as follows.

sns.clustermap(datadissimilarity, method='average', figsize=(40,40))
Jamie
  • 555
  • 3
  • 14

2 Answers2

2

sns.clustermap returns a 'clustergrid' which contains the subplots as 'axes': g.ax_col_dendrogram, g.ax_row_dendrogram, g.ax_heatmap, g.ax_col_colors, g.ax_row_colorsandg.ax_cbar`.

You can use these axes to calculate a bounding box of the desired areas. See also the second answer of Save a subplot in matplotlib about how to combine areas to select an exact area of interest.

import seaborn as sns; sns.set_theme(color_codes=True)

iris = sns.load_dataset("iris")
species = iris.pop("species")
g = sns.clustermap(iris)

fig = g.fig
for ax, filename in zip([g.ax_col_dendrogram, g.ax_row_dendrogram, g.ax_heatmap],
                        ['col_dendrogram', 'row_dendrogram', 'heatmap']):
    extent = ax.get_tightbbox(fig.canvas.renderer).transformed(fig.dpi_scale_trans.inverted())
    fig.savefig(f'{filename}.png', bbox_inches=extent)
JohanC
  • 71,591
  • 8
  • 33
  • 66
1

You can save only part of the figure using bbox_inches= in the call to g.savefig().

The dendrograms and the heatmaps are located in separates Axes objects, that you can access using g.ax_row_dendrogram, g.ax_col_dendrogram, and g.ax_heatmap. You can use the figure transforms to get their position in inches to pass to bbox_inches.

iris = sns.load_dataset("iris")
species = iris.pop("species")
g = sns.clustermap(iris)

for ax,name in zip([g.ax_heatmap, g.ax_col_dendrogram, g.ax_row_dendrogram],
                   ['heatmap.png','col_dendrogram.png','row_dendrogram.png']):
    bbox = ax.get_window_extent()
    inches = g.fig.dpi_scale_trans.inverted().transform_bbox(bbox)
    g.savefig(name, bbox_inches=inches)
Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75