如何将自定义分类分布绘图函数生成的4幅图布局为2行2列子图
解决自定义绘图函数的子图布局问题
你的问题核心在于原函数每次调用都会独立创建新的Figure对象,而plt.subplot()只是在当前Figure上创建子图坐标轴,但函数内部的plot.bar()会自动生成新的Figure,导致你的子图布局代码根本无法控制这些图的位置。
要实现2行2列的子图排版,我们需要修改class_distribution函数,让它支持传入指定的绘图坐标轴,从而把每个图画到预先规划好的子图位置上。
修改后的函数代码
def class_distribution(colname, ax=None): # 如果没有传入坐标轴,默认使用当前坐标轴(保留原函数的兼容性) if ax is None: ax = plt.gca() df = tweets_best.groupby(["HandLabel", colname]).size().to_frame("size") df['percentage'] = df.groupby(level=0).transform(lambda x: (x / x.sum()).round(2)) df_toPlot = df[["percentage"]] # 把图画到传入的目标坐标轴上 df_toPlot.unstack().plot.bar(ax=ax) ax.legend(df_toPlot.index.get_level_values(level = 1)) ax.set_title("{} predicted sentiment distribution".format(colname)) ax.set_ylim((0,1)) ax.yaxis.set_major_formatter(PercentFormatter(1)) # 返回当前坐标轴所属的画布(可选,按需使用) return ax.get_figure()
调用示例(2行2列子图布局)
# 创建2行2列的子图布局,获取所有坐标轴对象,可自定义画布大小 fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8)) # 分别将每个子图坐标轴传入函数,绘制对应图表 class_distribution("Naive_Bayes", ax=axes[0,0]) class_distribution("SVM", ax=axes[0,1]) class_distribution("Logistic_Regression", ax=axes[1,0]) class_distribution("Random_Forest", ax=axes[1,1]) # 自动调整子图间距,避免标题、标签重叠 plt.tight_layout() # 按需保存整个画布 # fig.savefig("sentiment_distributions.png")
关键改动说明
- 添加
ax=None参数,允许外部指定绘图的目标坐标轴 - 将原函数中所有
plt全局绘图操作,替换为传入的ax对象的方法(比如ax.set_title()替代plt.title()) - 绘图时通过
plot.bar(ax=ax)强制指定绘制到目标坐标轴上
这样修改后,你就能完全控制每个图表在子图布局中的位置,轻松实现2行2列的排版效果。
内容的提问来源于stack exchange,提问作者GKroch




