Seaborn使用plt.subplots绘制jointplot子图空白、排列错误如何解决
seaborn jointplot水平排列解决方案
问题原因
sns.jointplot属于Figure级别的绘图接口,本身会自动生成独立的画布和轴系,不支持传入plt.subplots()创建的普通轴对象。你提前创建的fig, axes = plt.subplots(1, 2)生成的两个轴没有被使用,就变成了顶部的空白图。- 每次调用
sns.jointplot都会生成独立的新画布,默认按顺序垂直堆叠展示,不会自动适配你提前创建的水平子图网格,所以出现垂直排列的问题。
可直接运行的修改后代码
import seaborn as sns import matplotlib.pyplot as plt import numpy as np sns.set(style="darkgrid") iris = sns.load_dataset("iris") # 创建总画布,用gridspec划分适配jointplot结构的网格,总宽度按两个jointplot等分 fig = plt.figure(figsize=(12, 6)) gs = fig.add_gridspec(2, 6, width_ratios=[3, 1, 0.2, 3, 1, 0.2], height_ratios=[1, 3]) # 分配左侧第一个jointplot的三个轴位置:主绘图区、上侧边际分布区、右侧边际分布区 ax1_joint = fig.add_subplot(gs[1, 0:2]) ax1_marg_x = fig.add_subplot(gs[0, 0:2], sharex=ax1_joint) ax1_marg_y = fig.add_subplot(gs[1, 2], sharey=ax1_joint) # 分配右侧第二个jointplot的三个轴位置 ax2_joint = fig.add_subplot(gs[1, 3:5]) ax2_marg_x = fig.add_subplot(gs[0, 3:5], sharex=ax2_joint) ax2_marg_y = fig.add_subplot(gs[1, 5], sharey=ax2_joint) # 隐藏边际图的冗余刻度,避免重复显示 plt.setp(ax1_marg_x.get_xticklabels(), visible=False) plt.setp(ax1_marg_y.get_yticklabels(), visible=False) plt.setp(ax2_marg_x.get_xticklabels(), visible=False) plt.setp(ax2_marg_y.get_yticklabels(), visible=False) # 绘制第一个jointplot,手动指定三个轴,避免自动生成新画布 g1 = sns.JointGrid(x="sepal_width", y="sepal_length", data=iris, ax_joint=ax1_joint, ax_marg_x=ax1_marg_x, ax_marg_y=ax1_marg_y) g1.plot_joint(sns.regplot, color='k') g1.plot_marginals(sns.histplot, kde=True, color='k') # 替换主绘图区为带尺寸映射的散点图 g1.ax_joint.cla() sns.scatterplot(data=iris, x='sepal_width', y='sepal_length', size='petal_length', sizes=(10, 200), ax=g1.ax_joint) # 绘制第二个jointplot g2 = sns.JointGrid(x="sepal_width", y="sepal_length", data=iris, ax_joint=ax2_joint, ax_marg_x=ax2_marg_x, ax_marg_y=ax2_marg_y) g2.plot_joint(sns.regplot, color='k') g2.plot_marginals(sns.histplot, kde=True, color='k') # 替换主绘图区为带尺寸映射的散点图 g2.ax_joint.cla() sns.scatterplot(data=iris, x='sepal_width', y='sepal_length', size='petal_width', sizes=(10, 200), ax=g2.ax_joint) # 调整子图间距避免重叠 plt.tight_layout() plt.show()
修改核心要点
- 改用
matplotlib.gridspec划分适配jointplot三部分(主绘图区、上下边际分布区)的网格结构,分别给两个jointplot分配左右对应的位置,实现水平排列 - 调用底层的
sns.JointGrid接口手动指定轴位置,避免接口自动生成多余画布,消除顶部空白图 - 保留原有需求的回归拟合线、边际分布、散点尺寸映射逻辑,无需修改业务绘图逻辑
内容的提问来源于stack exchange,提问作者H42
相关产品推荐
相关产品推荐

