Seaborn 子图函数
Seaborn 是基于 Matplotlib 来实现的,如果想要在 Seaborn 中绘制多个子图,我们可以使用 Matplotlib 提供的 subplots() 函数来实现。注意,这里的 subplots 后面有一个 “s”。
语法:
fig, axes = plt.subplots(nrows, ncols, sharex=False, sharey=False)说明:
subplots() 函数的主要参数有以下 4 个。
nrows(必选):用于定义行数。ncols(必选):用于定义列数。sharex(可选):用于定义是否共享 x 轴坐标,取值为 True 或 False(默认值为 False)。sharey(可选):用于定义是否共享 y 轴坐标,取值为 True 或 False(默认值为 False)。
subplots() 函数会返回 2 个对象:fig 和 axes。其中,fig 代表的是当前的画布对象。axes 是一个列表,该列表每一个元素都是一个区域对象。
示例 1:Seaborn 子图划分 2 个区域
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 设置
sns.set_theme(rc={'font.sans-serif': 'SimHei', 'axes.unicode_minus': False})
# 划分区域
fig, axes = plt.subplots(2, 1)
# 绘制折线图
data = [
[1, 16],
[2, 15],
[3, 16],
[4, 18],
[5, 17]
]
df = pd.DataFrame(data, columns=['日期', '气温'])
sns.lineplot(data=df, x='日期', y='气温', ax=axes[0])
# 显示
plt.show()运行之后,效果如下图所示。

分析:
fig, axes = plt.subplots(2, 1) 表示将画布划分为 2 × 1 = 2 个子区域,此时整个画布的布局如下图所示。使用 suplots() 函数划分区域之后,我们还需要在绘图函数中使用 ax 这个参数来指定该图表在哪一个子区域中绘制。

示例 2:Seaborn 子图划分 4 个区域
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 设置
sns.set_theme(rc={'font.sans-serif': 'SimHei', 'axes.unicode_minus': False})
# 划分区域
fig, axes = plt.subplots(2, 2)
# 绘制折线图
data = [
[1, 16],
[2, 15],
[3, 16],
[4, 18],
[5, 17]
]
df = pd.DataFrame(data, columns=['日期', '气温'])
sns.lineplot(data=df, x='日期', y='气温', ax=axes[0, 0])
# 显示
plt.show()运行之后,效果如下图所示。

分析:
fig, axes = plt.subplots(2, 2) 表示将画布划分为 2 × 2 = 4 个子区域,此时整个画布的布局如下图所示。需要注意的是,如果想要指定在第 1 个子区域绘制,此时 ax 的值应该是 axes[0, 0] 而不是 ax[0]。

Seaborn 子图案例
接下来我们尝试绘制一个 2 × 2 的组合图表,也就是在同一张画布上绘制 4 种不同的图表:折线图、散点图、柱状图、箱线图。
示例 3:Seaborn 子图的应用
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 设置
sns.set_theme(rc={'font.sans-serif': 'SimHei', 'axes.unicode_minus': False})
# 划分区域
fig, axes = plt.subplots(2, 2)
# 绘制折线图
def drawline():
data = [
[1, 16],
[2, 15],
[3, 16],
[4, 18],
[5, 17]
]
df = pd.DataFrame(data, columns=['日期', '气温'])
sns.lineplot(data=df, x='日期', y='气温', ax=axes[0, 0])
# 绘制散点图
def drawscatter():
data = [
[1, 16],
[2, 18],
[3, 20],
[4, 21],
[5, 21]
]
df = pd.DataFrame(data, columns=['A列', 'B列'])
sns.scatterplot(data=df, x='A列', y='B列', ax=axes[0, 1])
# 绘制柱形图
def drawbar():
data = [
['1月', 468],
['2月', 521],
['3月', 362],
['4月', 227],
['5月', 438],
['6月', 550]
]
df = pd.DataFrame(data, columns=['月份', '销量'])
sns.barplot(data=df, x='月份', y='销量', ax=axes[1, 0])
# 绘制箱线图
def drawbox():
data = [
['张三', 24],
['李四', 18],
['王五', 37],
['小芳', 24],
['小红', 12],
['小明', 42],
['小华', 56],
['小莉', 67],
['小英', 45],
['小军', 120]
]
df = pd.DataFrame(data, columns=['姓名', '年龄'])
sns.boxplot(data=df, y='年龄', ax=axes[1, 1])
# 调用函数
drawline()
drawscatter()
drawbar()
drawbox()
# 调整布局
plt.tight_layout()
# 显示图表
plt.show()运行之后,效果如下图所示。

分析:
这个例子代码虽然比较多,但是逻辑是非常简单的。其中,plt.tight_layout() 用于调整子图之间的布局。如果没有这一句代码,子图之间就可能出现覆盖的情况,如下图所示。

需要特别注意的是,Seaborn 中有一类 “Figure-level(图级)函数”(如 catplot、relplot、displot),它们默认会创建新的画布,因此不支持 ax 参数,无法直接嵌入到 plt.subplots 创建的子图中。只有 “Axes-level(轴级)函数”(如 scatterplot、boxplot、histplot 等)才支持子图绘制。
