Seaborn绘制子图异常:指定子图被覆盖为最后一个子图
问题:Seaborn绘制多子图时,子图指针被意外覆盖为最后一个子图
尝试在单个画布中绘制多个子图时发现异常:执行axS[i] = sns.boxplot(plot)后,Seaborn始终选择最后一个子图,两次打印axS[i]的结果不一致——第一次能正确指向对应子图,调用绘图函数后指针变为最后一个子图的指针。
问题代码
df = pd.read_csv(fold+file,index_col=1) print(df.columns) types = ['all cells','1 endothelial','2 immune','3 tumor','4 active fibroblast','5 stromal'] fig,axS = plt.subplots(6,1,sharex=True,figsize=(20,8)) for i,ty in enumerate(types): if i == 0: plot = df.loc[:,bioms] else: key = df.loc[:,'SVM_primary'] == ty sdf = df.loc[key,bioms] plot = sdf print('\n',i,ty) print(axS[i]) #First important print statement axS[i] = sns.boxplot(plot) print(axS[i]) #Second: should be identical, but it's not! axS[i].title.set_text(ty) plt.xticks(rotation = 90) fig.tight_layout() plt.show()
输出结果
0 all cells AxesSubplot(0.125,0.77;0.775x0.11) AxesSubplot(0.125,0.11;0.775x0.11) 1 1 endothelial AxesSubplot(0.125,0.638;0.775x0.11) # AxesSubplot(0.125,0.11;0.775x0.11) # this pointer should be the same as the one above it 2 2 immune AxesSubplot(0.125,0.506;0.775x0.11) AxesSubplot(0.125,0.11;0.775x0.11) 3 3 tumor AxesSubplot(0.125,0.374;0.775x0.11) AxesSubplot(0.125,0.11;0.775x0.11) 4 4 active fibroblast AxesSubplot(0.125,0.242;0.775x0.11) AxesSubplot(0.125,0.11;0.775x0.11) 5 5 stromal AxesSubplot(0.125,0.11;0.775x0.11) AxesSubplot(0.125,0.11;0.775x0.11)
原因分析与解决方法
问题根源
- Seaborn的
boxplot函数如果不指定ax参数,会默认使用当前活动的Matplotlib轴对象(创建6个子图后,默认活动轴是最后一个子图axS[5]) - 执行
axS[i] = sns.boxplot(plot)时,会把boxplot返回的默认轴(也就是最后一个子图)覆盖掉原来的axS[i],导致后续设置标题等操作全部指向最后一个子图
解决方法
不要重新赋值axS[i],而是给boxplot指定ax参数,直接在目标子图上绘制:
将axS[i] = sns.boxplot(plot)修改为:
sns.boxplot(data=plot, ax=axS[i])
修改后的完整代码
df = pd.read_csv(fold+file,index_col=1) print(df.columns) types = ['all cells','1 endothelial','2 immune','3 tumor','4 active fibroblast','5 stromal'] fig,axS = plt.subplots(6,1,sharex=True,figsize=(20,8)) for i,ty in enumerate(types): if i == 0: plot = df.loc[:,bioms] else: key = df.loc[:,'SVM_primary'] == ty sdf = df.loc[key,bioms] plot = sdf print('\n',i,ty) print(axS[i]) sns.boxplot(data=plot, ax=axS[i]) # 指定ax参数,不覆盖原轴对象 print(axS[i]) axS[i].title.set_text(ty) plt.xticks(rotation = 90) fig.tight_layout() plt.show()
这样修改后,axS[i]始终指向你创建的对应子图,绘图和标题设置都会正确作用在目标子图上。
内容的提问来源于stack exchange,提问作者yohsu
相关产品推荐
相关产品推荐

