Scanpy循环生成t-SNE图仅首个正常,后两个子图为空的问题排查
Scanpy循环绘制多子图t-SNE仅第一个显示的问题排查与解决
以下是导致仅第一个子图正常显示、其余为空的常见原因及对应解决方案:
1. 未显式指定绘图的子图轴对象(最常见)
Scanpy的sc.pl.tsne()默认会创建新的Matplotlib画布,若循环中未将每个子图的ax对象传入函数,后续绘图会脱离当前子图网格,导致后续子图为空。
错误示例(无ax参数):
fig, axes = plt.subplots(1,3) for i, cond in enumerate(['AB','AC','AD']): adata_sub = adata_all[adata_all.obs['condition'] == cond] sc.pl.tsne(adata_sub) # 默认创建新画布,不使用axes[i]
修正方法:
给sc.pl.tsne()添加ax=axes[i]参数,指定绘图到对应子图,同时设置show=False避免提前显示画布:
fig, axes = plt.subplots(1, 3, figsize=(15,5)) conditions = ['AB','AC','AD'] for i, cond in enumerate(conditions): adata_sub = adata_all[adata_all.obs['condition'] == cond].copy() # 指定子图轴并关闭自动显示 sc.pl.tsne(adata_sub, ax=axes[i], title=f'Condition: {cond}', show=False) plt.tight_layout() plt.show()
2. 子集化后的adata未计算t-SNE嵌入
若仅在全数据集adata_all上计算了t-SNE,子集化后的adata_sub可能没有对应的obsm['X_tsne']键,导致绘图时无数据可展示。
修正方法:
在循环内为每个子集重新计算t-SNE(全数据集的嵌入不适用于子集,单独计算更合理):
fig, axes = plt.subplots(1, 3, figsize=(15,5)) conditions = ['AB','AC','AD'] for i, cond in enumerate(conditions): adata_sub = adata_all[adata_all.obs['condition'] == cond].copy() # 检查是否存在t-SNE嵌入,不存在则计算 if 'X_tsne' not in adata_sub.obsm: sc.tl.tsne(adata_sub, perplexity=30) # 根据数据规模调整perplexity参数 sc.pl.tsne(adata_sub, ax=axes[i], title=f'Condition: {cond}', show=False) plt.tight_layout() plt.show()
3. 循环中子图索引错误
若创建子图时的轴对象遍历方式错误(比如误将1D轴数组当作2D处理),会导致后续子图未被正确赋值。
错误示例:
fig, axes = plt.subplots(1,3) for i in range(3): # 错误使用二维索引,1行3列的axes是一维数组 sc.pl.tsne(adata_sub, ax=axes[0,i], show=False)
修正方法:
直接使用一维索引axes[i]遍历子图轴对象。
4. 循环内过早调用plt.show()
若在循环内部调用plt.show(),会关闭当前画布,后续绘图无法在原有子图网格中展示。
错误示例:
for i, cond in enumerate(conditions): sc.pl.tsne(adata_sub, ax=axes[i], show=True) # 每次循环都显示画布,导致后续子图失效
修正方法:
循环内设置show=False,最后统一调用plt.show()。
内容的提问来源于stack exchange,提问作者minoo
相关产品推荐
相关产品推荐

