subplot()、subplots()均用于Matplotlib 绘制多图,我们需要理解它的实际工作流程和返回对象的含义,才能更好的用它们来处理大型的数据。

1.从两者的区别来谈谈函数返回对象:

菜鸟教程原文解释:

  • subplots 一次性创建并返回所有的子图和其 axe 对象。subplot则是分开多次添加子图。每次调用返回一个子图和对应的 ax 对象。
    不知道你第一次看到这段话是否迷惑,反正我是迷了,后来看了大量教程发现这样的说法是极其模糊和不准确的。 来让我们搞懂它们吧

来看这段常见代码:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()

这里fig和ax是两个subplots()的返回对象,名称当然可以自定义
实际的含义是什么呢?这个才是最重要的
我的理解:

  • fig-------即figure,画窗,图形对象。
  • ax-------即axex,画窗中创建的笛卡尔坐标区

上面的代码,是下面代码的精简形式:

fig = plt.figure()  # 首先调用plt.figure()创建了一个**画窗对象fig**
ax = fig.add_subplot(111)  # 然后再对fix创建默认的坐标区(一行一列一个坐标区)
# 这里的(111)相当于(1,1,1),当然,官方有规定,当子区域不超过9个的时候,我们可以这样简写

1.1 plt.subplot()

关于 subplot():
来看 matplotlib.pyplot.subplot 的官方解释:

在这里插入图片描述
注意这句:This is a wrapper of Figure.add_subplot which provides additional behavior when working with the implicit API (see the notes section).
即是对add_subplot()函数的封装调用。

1.2 add_subplot()

再来看add_subplot():
在这里插入图片描述
意思就是用来向画窗添加坐标区的。

那么我们可以进行总结了:
subplot()、subplots()在实际过程中,先创建了一个figure画窗,然后通过调用add_subplot()来向画窗中各个分块添加坐标区,其差别在于是分次添加(subplot())还是一次性添加(subplots()).

1.3 三者区别

下面通俗地解释 plt.subplotsadd_subplot() 的区别,有助于更好地理解它们的用途和场景。

1.3.1 plt.subplotsplt.subplot 的区别

  1. plt.subplots

    • plt.subplots 是创建一整个图形(figure)和其中多个子图(axes)的一个方便函数。
    • 它一次性生成一个包含所有子图的图形,并返回图形对象和子图对象。
    • 用法:fig, axes = plt.subplots(nrows, ncols),其中 nrows 是行数,ncols 是列数。axes 是一个包含所有子图对象的数组。

    例子

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 2 * np.pi, 100)
    y_sin = np.sin(x)
    y_cos = np.cos(x)
    
    # 使用 plt.subplots 创建一个包含两个子图的图形
    fig, axes = plt.subplots(1, 2, figsize=(10, 5))
    
    # 绘制第一个子图
    axes[0].plot(x, y_sin, label='sin(x)')
    axes[0].set_title('Sine Function')
    axes[0].set_xlabel('x')
    axes[0].set_ylabel('sin(x)')
    axes[0].legend()
    
    # 绘制第二个子图
    axes[1].plot(x, y_cos, label='cos(x)')
    axes[1].set_title('Cosine Function')
    axes[1].set_xlabel('x')
    axes[1].set_ylabel('cos(x)')
    axes[1].legend()
    
    plt.tight_layout()
    plt.show()
    
  2. plt.subplot

    • plt.subplot 是一个逐个添加子图的函数。
    • 它需要你每次调用时指定行、列和子图位置,然后在这个子图上绘制内容。
    • 用法:plt.subplot(nrows, ncols, index),其中 nrows 是行数,ncols 是列数,index 是子图位置。

    例子

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 2 * np.pi, 100)
    y_sin = np.sin(x)
    y_cos = np.cos(x)
    
    # 创建一个包含两个子图的图形
    plt.figure(figsize=(10, 5))
    
    # 绘制第一个子图
    plt.subplot(1, 2, 1)  # 1行2列,第1个子图
    plt.plot(x, y_sin, label='sin(x)')
    plt.title('Sine Function')
    plt.xlabel('x')
    plt.ylabel('sin(x)')
    plt.legend()
    
    # 绘制第二个子图
    plt.subplot(1, 2, 2)  # 1行2列,第2个子图
    plt.plot(x, y_cos, label='cos(x)')
    plt.title('Cosine Function')
    plt.xlabel('x')
    plt.ylabel('cos(x)')
    plt.legend()
    
    plt.tight_layout()
    plt.show()
    

1.3.2 plt.subplotsadd_subplot 的区别

  1. plt.subplots:

    • 一次性创建整个图形和多个子图,并返回图形和子图对象。
    • 更加简洁和高效,尤其是当你需要创建多个子图时。
    • 使用 axes 对象数组来访问和操作子图。
  2. add_subplot:

    • Figure 对象的方法,用于逐个添加子图。
    • 每次调用 add_subplot 时,都会返回一个新的子图对象。
    • 适用于需要动态条件性地添加子图的情况。

    例子

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 2 * np.pi, 100)
    y_sin = np.sin(x)
    y_cos = np.cos(x)
    
    # 创建一个图形对象
    fig = plt.figure(figsize=(10, 5))
    
    # 添加第一个子图
    ax1 = fig.add_subplot(1, 2, 1)
    ax1.plot(x, y_sin, label='sin(x)')
    ax1.set_title('Sine Function')
    ax1.set_xlabel('x')
    ax1.set_ylabel('sin(x)')
    ax1.legend()
    
    # 添加第二个子图
    ax2 = fig.add_subplot(1, 2, 2)
    ax2.plot(x, y_cos, label='cos(x)')
    ax2.set_title('Cosine Function')
    ax2.set_xlabel('x')
    ax2.set_ylabel('cos(x)')
    ax2.legend()
    
    plt.tight_layout()
    plt.show()
    

1.3.3 总结

  • plt.subplots 更适合一次性创建和管理多个子图,代码更简洁。
  • plt.subplot 适合逐个创建子图,灵活性更高。
  • add_subplotFigure 对象的方法,适合动态添加子图。

2. 应用案例

2.1 plt.figure() + fig.add_subplot() 单个图

# 可视化联合概率密度的3D图
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
ti_grid = np.full(alp2_grid.shape, ti_fixed_value)  
joint_density = kde(np.vstack([alp2_grid.ravel(), air_density_grid.ravel(), ti_grid.ravel()])).reshape(
    alp2_grid.shape)
ax.plot_surface(alp2_grid, air_density_grid, joint_density, cmap='viridis', alpha=0.7)
ax.set_xlabel('alp2')
ax.set_ylabel('air_density')
ax.set_zlabel('Density')
ax.set_title('Joint Probability')
plt.show()

2.2 plt.subplots() 单个图(简洁)

fig, ax = plt.subplots(figsize=(10, 6))
cs = ax.contourf(alp2_grid, air_density_grid, condition_density, cmap='viridis')
plt.colorbar(cs, ax=ax)
ax.set_xlabel('alp2')
ax.set_ylabel('air_density')
ax.set_title(f'Conditional Probability')
plt.show()

2.3 plt.subplots() 多图(简洁)

# 设置Seaborn风格
sns.set(style="whitegrid")
# 创建一个2x2的图形布局
fig, axes = plt.subplots(1, 3, figsize=(18, 6))

# 设置Y轴范围
y_limits = {
    'alp': (-0.25, 1),  # 根据数据分布调整范围
    'TI': (-0.05, 0.2),
    'shear': (-0.2, 0.5),
    'air_density': (0.6, 1.5)
}
# 绘制'ALP'的箱线图
sns.boxplot(x='terrain', y='alp', data=data, ax=axes[0], palette='Set2')
axes[0].set_title('alp vs Terrain')
axes[0].set_xlabel('Terrain')
axes[0].set_ylabel('alp')
axes[0].set_ylim(y_limits['alp'])
axes[0].axhline(y=0.11, color='red', linewidth=0.5)

# 绘制'TI'的箱线图
sns.boxplot(x='terrain', y='TI', data=data, ax=axes[1], palette='Set2')
axes[1].set_title('TI vs Terrain')
axes[1].set_xlabel('Terrain')
axes[1].set_ylabel('TI')
axes[1].set_ylim(y_limits['TI'])
axes[1].axhline(y=0.11, color='red', linewidth=0.5)
# 绘制'Shear'的箱线图
sns.boxplot(x='terrain', y='air_density', data=data, ax=axes[2], palette='Set2')
axes[2].set_title('air_density vs Terrain')
axes[2].set_xlabel('Terrain')
axes[2].set_ylabel('air_density')
axes[2].set_ylim(y_limits['air_density'])
axes[2].axhline(y=1.0, color='red', linewidth=0.5)

plt.rcParams['font.sans-serif'] = ['SimHei']  # 运行配置参数中的字体(font)为黑体(SimHei)
plt.rcParams['axes.unicode_minus'] = False  # 运行配置参数总的轴(axes)正常显示正负号(minus)

# 显示图形
plt.tight_layout()
if status:
    plt.savefig(r'df_all_medial_max_by_{}-{}.jpg'.format('terrain', datetime.now().strftime('%m%d_%H%M')))
else:
    plt.show()

2.4 plt.subplot() 多图(简洁)

下面是一个使用 plt.subplot 的示例,它展示了如何在同一图中绘制多个子图。绘制两个子图:一个是正弦函数图,一个是余弦函数图。

import matplotlib.pyplot as plt
import numpy as np

# 生成数据
x = np.linspace(0, 2 * np.pi, 100)
y_sin = np.sin(x)
y_cos = np.cos(x)

# 创建一个包含两个子图的绘图区域
plt.figure(figsize=(10, 5))

# 第一个子图:正弦函数
plt.subplot(1, 2, 1)  # 1行2列,第1个子图
plt.plot(x, y_sin, label='sin(x)')
plt.title('Sine Function')
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.legend()

# 第二个子图:余弦函数
plt.subplot(1, 2, 2)  # 1行2列,第2个子图
plt.plot(x, y_cos, label='cos(x)')
plt.title('Cosine Function')
plt.xlabel('x')
plt.ylabel('cos(x)')
plt.legend()
# 调整布局,使子图不重叠
plt.tight_layout()
# 显示图形
plt.show()

在这里插入图片描述

解释

  1. 生成数据:使用 np.linspace 生成一个从 0 到 ( 2\pi ) 的 100 个点,然后计算对应的正弦和余弦值。
  2. 创建绘图区域:使用 plt.figure 创建一个绘图区域,并设置图形大小为 10 x 5 英寸。
  3. 第一个子图
    • 使用 plt.subplot(1, 2, 1) 创建一个 1 行 2 列的子图,并选择第一个位置。
    • 使用 plt.plot 绘制正弦函数。
    • 添加标题、标签和图例。
  4. 第二个子图
    • 使用 plt.subplot(1, 2, 2) 创建一个 1 行 2 列的子图,并选择第二个位置。
    • 使用 plt.plot 绘制余弦函数。
    • 添加标题、标签和图例。
  5. 调整布局:使用 plt.tight_layout 调整子图之间的间距,防止重叠。
  6. 显示图形:使用 plt.show 显示生成的图形。

这样,就可以在同一个图形中展示多个子图,每个子图显示不同的数据或函数。这对于比较不同的数据集或展示不同的图形非常有用。

参考资料

[1] plt: subplot()、subplots()详解及返回对象figure、axes的理解 2021.11;

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部