Search code examples
pythonpython-3.xmatplotlibseaborn

Adding seaborn clustermap to figure with other plots


I am trying to put the following two plots onto the same figure:

import seaborn as sns; sns.set(color_codes=True)
import matplotlib.pyplot as plt
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
iris = sns.load_dataset("iris")
sns.boxplot(data=iris, orient="h", palette="Set2", ax = ax1)
species = iris.pop("species")
lut = dict(zip(species.unique(), "rbg"))
row_colors = species.map(lut)
sns.clustermap(iris, row_colors=row_colors, ax = ax2)

I understand that clustermap returns a figure, so this doesn't work. However, I still need a way to present these plots next to each other (horizontal). sns.heatmap returns an axes, but it does not support clustering or color annotation .

What is the best way to do this ?


Solution

  • Indeed, clustermap, as some other seaborn functions, creates its own figure. There is nothing you can do about that but as long as all other content you want to have in the final figure can be created inside axes, like in this case the boxplot, the solution is relatively easy.

    You can simply work with the figure that clustermap has created for you. The idea would then be to manipulate the gridspec of the axes such that there is some place left for the other axes.

    import seaborn as sns; sns.set(color_codes=True)
    import matplotlib.pyplot as plt
    import matplotlib.gridspec
    
    iris = sns.load_dataset("iris")
    species = iris.pop("species")
    
    lut = dict(zip(species.unique(), "rbg"))
    row_colors = species.map(lut)
    
    #First create the clustermap figure
    g = sns.clustermap(iris, row_colors=row_colors, figsize=(13,8))
    # set the gridspec to only cover half of the figure
    g.gs.update(left=0.05, right=0.45)
    
    #create new gridspec for the right part
    gs2 = matplotlib.gridspec.GridSpec(1,1, left=0.6)
    # create axes within this new gridspec
    ax2 = g.fig.add_subplot(gs2[0])
    # plot boxplot in the new axes
    sns.boxplot(data=iris, orient="h", palette="Set2", ax = ax2)
    plt.show()
    

    enter image description here

    For the case when having multiple figure-level functions to combine the solution is much more complicated, as seen e.g. in this question.