Matplotlib如何实现带内嵌直方图的散点图并排绘制
自定义Matplotlib散点图函数适配水平并排子图方案
核心改造不需要重写原有业务逻辑,只要把所有依赖pyplot全局状态的调用替换为显式Axes对象调用即可,完全兼容原有单图使用习惯。
1. 函数入口改造
给原有scatter_plot新增可选ax入参,兼容新旧调用逻辑:
def scatter_plot(x, y, ax=None, **plot_kwargs): # 未传入子图对象时沿用原有全局轴逻辑,不影响之前的单图调用 if ax is None: ax = plt.gca() # 后续所有绘图操作全部基于ax对象实现,不再直接调用plt的全局绘图接口
2. 全局接口替换规则
把函数内所有pyplot全局调用逐行替换为Axes对象方法,对应关系如下:
- 散点绘制:
plt.scatter(...)→ax.scatter(...) - 回归线、参考线绘制:
plt.plot(...)→ax.plot(...) - RMSE、R²指标标注:
plt.text(...)→ax.text(...) - 百分位区域框选:
plt.gca().add_patch(rect)→ax.add_patch(rect) - 轴属性设置:
plt.xlim()/plt.ylim()/plt.xlabel()/plt.ylabel()/plt.title()→ 替换为ax.set_xlim()/ax.set_ylim()/ax.set_xlabel()/ax.set_ylabel()/ax.set_title()
3. 内嵌直方图适配(核心排错点)
之前子图内嵌图错位的核心原因是旧代码用plt.axes()创建内嵌轴时使用全局画布坐标,替换为相对父轴的内嵌轴创建方法即可:
弃用
plt.axes([left, bottom, width, height])的全局坐标写法,改用ax.inset_axes(),传入的位置参数是相对于当前传入ax的归一化坐标,无论ax在子图网格的哪个位置,内嵌图都会自动定位到对应子图内部。
示例替换代码:
# 旧写法(全局坐标,子图场景下位置错乱) # inset_ax = plt.axes([0.65, 0.15, 0.2, 0.2]) # inset_ax.hist(val, bins=10) # 新写法(相对当前子图坐标,自动适配) # 位置参数:[距ax左边界比例, 距ax下边界比例, 内嵌图宽度占比, 内嵌图高度占比] inset_ax = ax.inset_axes([0.65, 0.15, 0.2, 0.2]) inset_ax.hist(val, bins=10) # 内嵌轴的样式调整直接操作inset_ax即可,比如隐藏刻度 inset_ax.tick_params(axis='both', which='both', length=0) inset_ax.set_xticklabels([]) inset_ax.set_yticklabels([])
4. 并排子图调用方式
改造完成后,直接创建1行2列的子图网格,将对应Axes对象传入函数即可:
fig, (ax_left, ax_right) = plt.subplots(1, 2, figsize=(12, 5), dpi=120) # 左子图绘制 scatter_plot(x_data1, y_data1, ax=ax_left, 其余原有业务参数按之前的写法传入即可) # 右子图绘制 scatter_plot(x_data2, y_data2, ax=ax_right, 其余原有业务参数按之前的写法传入即可) # 自动调整子图间距避免标签重叠 plt.tight_layout() plt.show()
注意事项
- 改造过程中不要混用plt全局绘图接口和Axes对象方法,否则仍会出现图元错画到其他子图、画布被覆盖的问题
- 改造后原有单图调用
scatter_plot(x, y)不需要做任何修改,逻辑完全向后兼容 - 如果选区内嵌直方图有额外的区间标记、统计值标注,全部基于
inset_ax对象操作即可
内容的提问来源于stack exchange,提问作者Siddharth Singh Baghel
相关产品推荐
相关产品推荐

