You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Seaborn绘制多组子图面板遇空网格问题求助

子图绘制异常问题分析与解决

问题重现

尝试在单个画布中绘制3组各含3个绘图的子图面板,但最终得到一个空网格和3个独立的子图面板,效果如下:
效果图

相关代码如下:

绘图函数

def plot_qc_metrics(adata, key):
    
    pg.qc_metrics(adata, min_genes=100,  mito_prefix='MT-')
    pg.filter_data(adata)

    fig, ax = plt.subplots(1, 3, figsize=(15, 5), sharey=True)
    fig.suptitle(key, fontsize=16)

    sns.histplot(data = adata.obs, x = 'n_counts',  bins=50, log_scale=True, ax=ax[0])
    ax[0].set(xlim=(1, 100000), xlabel='log nUMI')

    data = adata.obs['n_genes']
    sns.histplot(data = adata.obs, x = 'n_genes',  bins=50, log_scale=True, ax=ax[1])
    ax[1].set(xlim=(1, 100000), xlabel='log nGenes')

    data = np.log2(adata.obs['percent_mito'])
    sns.histplot(data = data, x=data,  bins=100, ax=ax[2])
    ax[2].xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '$2^{%.0f}$' % x))

    return fig, ax

主调用代码

adata_dict = {
    'org_1': org_1, 
    'org_2': org_2, 
    'org_3': org_3
}

fig, ax = plt.subplots(nrows = 3, ncols = len(adata_dict), figsize=(15, 5), sharey=True)

for i, (key, adata) in enumerate(adata_dict.items()):
    subfig, subax = plot_qc_metrics(adata, key)
    ax[i] = subax

plt.tight_layout()
plt.show()

问题原因

  1. 重复创建画布:plot_qc_metrics函数内部每次都会执行fig, ax = plt.subplots(1, 3),这会生成新的独立画布,而非在你预先创建的大画布的子轴上绘图。
  2. 无效的轴赋值:尝试将subax赋值给ax[i]完全不起作用——matplotlib的轴对象无法通过这种方式替换,只会让预先创建的大画布轴保持空白,而函数里生成的新画布会单独显示。

修改方案

让绘图函数复用外部创建的轴对象,不再自行生成画布。具体修改如下:

修改后的绘图函数

def plot_qc_metrics(adata, key, ax_list):
    pg.qc_metrics(adata, min_genes=100,  mito_prefix='MT-')
    pg.filter_data(adata)

    # 直接使用传入的轴列表绘图
    sns.histplot(data=adata.obs, x='n_counts', bins=50, log_scale=True, ax=ax_list[0])
    ax_list[0].set(xlim=(1, 100000), xlabel='log nUMI')

    sns.histplot(data=adata.obs, x='n_genes', bins=50, log_scale=True, ax=ax_list[1])
    ax_list[1].set(xlim=(1, 100000), xlabel='log nGenes')

    data = np.log2(adata.obs['percent_mito'])
    sns.histplot(data=data, x=data, bins=100, ax=ax_list[2])
    ax_list[2].xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '$2^{%.0f}$' % x))

修改后的主调用代码

adata_dict = {
    'org_1': org_1, 
    'org_2': org_2, 
    'org_3': org_3
}

# 创建3行3列的子图网格,调整画布大小适配布局
fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(15, 12), sharey='row')

for i, (key, adata) in enumerate(adata_dict.items()):
    # 将当前行的3个轴传入绘图函数
    plot_qc_metrics(adata, key, ax[i])
    # 给每行添加数据集标题
    ax[i][0].set_ylabel(key, fontsize=14)

# 调整布局避免标题重叠
plt.tight_layout()
plt.subplots_adjust(top=0.92)
# 添加总标题
fig.suptitle('样本QC指标汇总', fontsize=18)
plt.show()

修改说明

  • 移除绘图函数内部创建画布的代码,改为接收外部传入的轴列表ax_list,直接在指定轴上绘图,避免生成独立画布。
  • 主代码创建3行3列的轴网格,每行对应一个数据集的3个QC图,将每行的轴传入函数完成绘图。
  • 调整画布大小和布局参数,确保标题与子图不重叠,提升可视化效果。

内容的提问来源于stack exchange,提问作者Carmen Sandoval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:01:15