使用单独的颜色条绘制多个Seaborn热图

时间:2020-10-01 19:09:43

标签: python seaborn heatmap subplot colorbar

是否可以将多个seaborn热图绘制到一个具有共享ytick标签和单个彩条的图形中,如下图所示?

enter image description here

我可以做的是使用以下代码分别绘制热图:

#图1

plt.figure()
sns.set()
comp = sns.heatmap(df, cmap="coolwarm", linewidths=.5, xticklabels=True, yticklabels=True, cbar_kws={"orientation": "horizontal", "label": "Pathway completeness", "pad": 0.004})
comp.set_xticklabels(comp.get_xticklabels(), rotation=-90)
comp.xaxis.tick_top() # x axis on top
comp.xaxis.set_label_position('top')
cbar = comp.collections[0].colorbar
cbar.set_ticks([0, 50, 100])
cbar.set_ticklabels(['0%', '50%', '100%'])          
figure = comp.get_figure()
figure.savefig("hetmap16.png", format='png', bbox_inches='tight')

#图2(图3相同,但是数据库不同)

plt.figure()
sns.set()
df = pd.DataFrame(heatMapFvaMinDictP)
fvaMax = sns.heatmap(df, cmap="rocket_r", linewidths=.5, xticklabels=True, cbar_kws={"orientation": "horizontal", "label": "Minimum average flux", "pad": 0.004})
fvaMax.set_xticklabels(fvaMax.get_xticklabels(), rotation=-90)
fvaMax.xaxis.tick_top() # x axis on top
fvaMax.xaxis.set_label_position('top')
fvaMax.tick_params(axis='y', labelleft=False)
figure = fvaMax.get_figure()
figure.savefig("fva1.png", format='png', bbox_inches='tight')

2 个答案:

答案 0 :(得分:1)

Seaborn基于matplotlib构建,可用于进一步自定义图。 plt.subplots(ncols=3, sharey=True, ...)创建三个共享y轴的子图。将ax=ax1添加到sns.heatmap(..., ax=...)会在所需子图上创建热图。请注意,sns.heatmap的返回值还是相同的ax

以下代码显示了一个示例。为第一个热图显式设置了vminvmax,以确保两个值都将出现在颜色栏中(默认颜色条在遇到的最小值和最大值之间运行)。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

sns.set()
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharey=True, figsize=(20, 8))

N = 20
labels = [''.join(np.random.choice(list('abcdefghi '), 40)) for _ in range(N)]
df = pd.DataFrame({'column 1': np.random.uniform(0, 100, N), 'column 2': np.random.uniform(0, 100, N)},
                  index=labels)
sns.heatmap(df, cmap="coolwarm", linewidths=.5, xticklabels=True, yticklabels=True, ax=ax1, vmin=0, vmax=100,
            cbar_kws={"orientation": "horizontal", "label": "Pathway completeness", "pad": 0.004})
ax1.set_xticklabels(ax1.get_xticklabels(), rotation=-90)
ax1.xaxis.tick_top()  # x axis on top
ax1.xaxis.set_label_position('top')
cbar = ax1.collections[0].colorbar
cbar.set_ticks([0, 50, 100])
cbar.set_ticklabels(['0%', '50%', '100%'])

for ax in (ax2, ax3):
    max_value = 10 if ax == ax2 else 1000
    df = pd.DataFrame({'column 1': np.random.uniform(0, max_value, N), 'column 2': np.random.uniform(0, max_value, N)},
                      index=labels)
    sns.heatmap(df, cmap="rocket_r", linewidths=.5, xticklabels=True, ax=ax,
                cbar_kws={"orientation": "horizontal", "pad": 0.004,
                          "label": ("Minimum" if ax == ax2 else "Minimum") + " average flux"})
    ax.set_xticklabels(ax.get_xticklabels(), rotation=-90)
    ax.xaxis.tick_top()  # x axis on top
    ax.xaxis.set_label_position('top')

plt.tight_layout()
fig.savefig("subplots.png", format='png', bbox_inches='tight')
plt.show()

enter image description here

答案 1 :(得分:1)

您可以将两个数据帧连接起来,并将FacetGridFacetGrid.map_dataframe一起使用,我想您可能需要稍微调整一下外观。没有您的数据,因此我尝试使用示例数据:

import pandas as pd
import numpy as np
import seaborn as sns

np.random.seed(111)
df1 = pd.DataFrame({'A':np.random.randn(15),'B':np.random.randn(15)},
                   index=['row_variable'+str(i+1) for i in range(15)])

df2 = pd.DataFrame({'A':np.random.randn(15),'B':np.random.randn(15)},
                   index=['row_variable'+str(i+1) for i in range(15)])

我们用一列为data.frame注释,表明与您一样的数据库,并为每个数据帧的配色方案设置字典:

df1['database'] = "database1"
df2['database'] = "database2"

dat = pd.concat([df1,df2])
cdict = {'database1':'rocket_r','database2':'coolwarm'}

并定义一个绘制热图的函数:

def heat(data,color):
    sns.heatmap(data[['A','B']],cmap=cdict[data['database'][0]],
                cbar_kws={"orientation": "horizontal"})

接下来的方面:

fg = sns.FacetGrid(data=dat, col='database',aspect=0.7,height=4)
fg.map_dataframe(heat)

enter image description here