Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

参考:plt.subplots

plt.subplots是Matplotlib库中一个强大而灵活的函数,用于创建包含多个子图的图形布局。它允许用户轻松地在一个图形窗口中组织和排列多个图表,非常适合用于数据可视化和科学绘图。本文将深入探讨plt.subplots的各种用法、参数和技巧,帮助你充分利用这个功能来创建复杂而美观的图表布局。

1. plt.subplots的基本用法

plt.subplots函数的基本语法如下:

fig, ax = plt.subplots(nrows, ncols, figsize=(width, height))

其中:
– fig:返回的Figure对象,代表整个图形
– ax:返回的Axes对象或Axes对象的数组,代表子图
– nrows:子图的行数
– ncols:子图的列数
– figsize:图形的尺寸,以英寸为单位

让我们从一个简单的例子开始:

import matplotlib.pyplot as plt
import numpy as np

# 创建一个2x2的子图布局
fig, axs = plt.subplots(2, 2, figsize=(10, 8))

# 在每个子图中绘制不同的内容
x = np.linspace(0, 10, 100)

axs[0, 0].plot(x, np.sin(x))
axs[0, 0].set_title('Sine Wave - how2matplotlib.com')

axs[0, 1].plot(x, np.cos(x))
axs[0, 1].set_title('Cosine Wave - how2matplotlib.com')

axs[1, 0].plot(x, np.exp(x))
axs[1, 0].set_title('Exponential Function - how2matplotlib.com')

axs[1, 1].plot(x, np.log(x))
axs[1, 1].set_title('Logarithmic Function - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了一个2×2的子图布局。axs是一个2D数组,我们可以通过索引来访问每个子图。我们在每个子图中绘制了不同的数学函数,并为每个子图设置了标题。

2. 调整子图布局

plt.subplots提供了多个参数来调整子图的布局:

2.1 figsize参数

figsize参数用于设置整个图形的大小,单位为英寸。例如:

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(12, 10))

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们将图形的大小设置为12×10英寸,这样可以得到一个更大的图形。

2.2 subplot_kw参数

subplot_kw参数允许我们为所有子图设置相同的关键字参数。例如:

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8), subplot_kw={'facecolor': 'lightgray'})

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们使用subplot_kw参数为所有子图设置了浅灰色的背景。

2.3 gridspec_kw参数

gridspec_kw参数允许我们更精细地控制子图的布局。例如:

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8), 
                        gridspec_kw={'width_ratios': [2, 1], 'height_ratios': [1, 2]})

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们使用gridspec_kw参数设置了不同的宽度比和高度比,使得左列的子图比右列宽,下行的子图比上行高。

3. 创建不同形状的子图布局

plt.subplots不仅可以创建规则的网格布局,还可以创建不同形状的子图布局。

3.1 创建单行或单列的子图

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(1, 3, figsize=(15, 5))

x = np.linspace(0, 10, 100)

for i in range(3):
    axs[i].plot(x, np.sin(x + i))
    axs[i].set_title(f'Sine Wave {i+1} - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子创建了一个包含3个子图的单行布局。

3.2 创建不规则的子图布局

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 3, figsize=(15, 10))

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(3):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

# 移除一些子图
fig.delaxes(axs[1, 2])
fig.delaxes(axs[1, 1])

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们首先创建了一个2×3的子图布局,然后使用fig.delaxes()方法移除了一些子图,从而创建了一个不规则的布局。

4. 共享轴

plt.subplots允许子图之间共享x轴或y轴,这在比较多个相关数据集时非常有用。

4.1 共享x轴

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), sharex=True)

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax2.plot(x, np.cos(x))
ax2.set_title('Cosine Wave - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了两个垂直排列的子图,并通过设置sharex=True使它们共享x轴。

4.2 共享y轴

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6), sharey=True)

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax2.plot(x, np.cos(x))
ax2.set_title('Cosine Wave - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子创建了两个水平排列的子图,并通过设置sharey=True使它们共享y轴。

5. 调整子图间距

plt.subplots提供了几个参数来调整子图之间的间距:

5.1 使用hspace和wspace

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8))

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

plt.subplots_adjust(hspace=0.5, wspace=0.5)
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们使用plt.subplots_adjust()函数来增加子图之间的水平和垂直间距。

5.2 使用gridspec_kw

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8), 
                        gridspec_kw={'hspace': 0.4, 'wspace': 0.4})

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')

plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子展示了如何使用gridspec_kw参数来调整子图间距。

6. 创建不同大小的子图

有时我们可能需要创建大小不同的子图。这可以通过gridspec_kw参数来实现:

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(12, 10), 
                        gridspec_kw={'height_ratios': [2, 1], 'width_ratios': [1, 2]})

x = np.linspace(0, 10, 100)

axs[0, 0].plot(x, np.sin(x))
axs[0, 0].set_title('Sine Wave - how2matplotlib.com')

axs[0, 1].plot(x, np.cos(x))
axs[0, 1].set_title('Cosine Wave - how2matplotlib.com')

axs[1, 0].plot(x, np.exp(x))
axs[1, 0].set_title('Exponential Function - how2matplotlib.com')

axs[1, 1].plot(x, np.log(x))
axs[1, 1].set_title('Logarithmic Function - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了一个2×2的子图布局,其中上面的子图比下面的高,右边的子图比左边的宽。

7. 创建嵌套的子图

plt.subplots还可以用来创建嵌套的子图布局:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12, 8))

# 创建主子图
gs = fig.add_gridspec(2, 2)

ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])

# 在右上角的子图中创建嵌套的子图
gs_nested = gs[0, 1].subgridspec(2, 2)
ax2_1 = fig.add_subplot(gs_nested[0, 0])
ax2_2 = fig.add_subplot(gs_nested[0, 1])
ax2_3 = fig.add_subplot(gs_nested[1, 0])
ax2_4 = fig.add_subplot(gs_nested[1, 1])

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax3.plot(x, np.cos(x))
ax3.set_title('Cosine Wave - how2matplotlib.com')

for ax in [ax2_1, ax2_2, ax2_3, ax2_4]:
    ax.plot(x, np.random.rand(100))
    ax.set_title('Random Data - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子展示了如何创建一个复杂的嵌套子图布局。我们首先创建了一个2×2的主布局,然后在右上角的子图中嵌套了一个2×2的子布局。

8. 使用constrained_layout

constrained_layout是一个新的自动布局机制,可以自动调整子图的大小和位置,以避免重叠和不一致的间距:

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)

x = np.linspace(0, 10, 100)

for i in range(2):
    for j in range(2):
        axs[i, j].plot(x, np.sin(x + i + j))
        axs[i, j].set_title(f'Sine Wave {i+1},{j+1} - how2matplotlib.com')
        axs[i, j].set_xlabel('X axis')
        axs[i, j].set_ylabel('Y axis')

plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们使用constrained_layout=True来自动调整子图布局,这样可以确保所有的标签和标题都能完整显示,而不会相互重叠。

9. 创建3D子图plt.subplots不仅可以创建2D子图,还可以创建3D子图:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

fig, axs = plt.subplots(2, 2, figsize=(12, 10), subplot_kw={'projection': '3d'})

x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)

for i in range(2):
    for j in range(2):
        Z = np.sin(np.sqrt(X**2 + Y**2) + i + j)
        axs[i, j].plot_surface(X, Y, Z, cmap='viridis')
        axs[i, j].set_title(f'3D Surface {i+1},{j+1} - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了四个3D子图,每个子图都显示了一个稍微不同的3D表面。

10. 使用不同的投影

plt.subplots还允许我们在同一个图形中使用不同的投影:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(12, 10))

ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222, projection='polar')
ax3 = fig.add_subplot(223, projection='3d')
ax4 = fig.add_subplot(224)

# 2D plot
x = np.linspace(0, 10, 100)
ax1.plot(x, np.sin(x))
ax1.set_title('2D Plot - how2matplotlib.com')

# Polar plot
theta = np.linspace(0, 2*np.pi, 100)
r = np.cos(4*theta)
ax2.plot(theta, r)
ax2.set_title('Polar Plot - how2matplotlib.com')

# 3D plot
X, Y = np.meshgrid(x, x)
Z = np.sin(np.sqrt(X**2 + Y**2))
ax3.plot_surface(X, Y, Z, cmap='viridis')
ax3.set_title('3D Plot - how2matplotlib.com')

# Image plot
img = np.random.rand(10, 10)
ax4.imshow(img, cmap='gray')
ax4.set_title('Image Plot - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子展示了如何在一个图形中创建四个不同类型的子图:一个普通的2D图,一个极坐标图,一个3D图,和一个图像显示。

11. 创建非矩形布局

虽然plt.subplots通常用于创建矩形网格布局,但我们也可以使用它来创建更复杂的非矩形布局:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12, 8))

gs = fig.add_gridspec(3, 3)

ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :-1])
ax3 = fig.add_subplot(gs[1:, -1])
ax4 = fig.add_subplot(gs[-1, 0])
ax5 = fig.add_subplot(gs[-1, -2])

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax2.plot(x, np.cos(x))
ax2.set_title('Cosine Wave - how2matplotlib.com')

ax3.plot(x, np.tan(x))
ax3.set_title('Tangent Wave - how2matplotlib.com')

ax4.plot(x, np.exp(x))
ax4.set_title('Exponential Function - how2matplotlib.com')

ax5.plot(x, np.log(x))
ax5.set_title('Logarithmic Function - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个例子创建了一个非矩形的布局,包括一个跨越整个顶部的子图,一个占据中间两列的子图,一个占据右侧两行的子图,以及底部的两个小子图。

12. 使用add_subplot方法

除了使用plt.subplots,我们还可以使用Figure对象的add_subplot方法来逐个添加子图:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12, 8))

ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax2.plot(x, np.cos(x))
ax2.set_title('Cosine Wave - how2matplotlib.com')

ax3.plot(x, np.exp(x))
ax3.set_title('Exponential Function - how2matplotlib.com')

ax4.plot(x, np.log(x))
ax4.set_title('Logarithmic Function - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

这个方法给了我们更多的灵活性,因为我们可以在任何时候添加新的子图,而不需要预先知道子图的总数。

13. 使用subplot2grid

subplot2grid是另一个用于创建复杂布局的有用工具:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12, 8))

ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))

x = np.linspace(0, 10, 100)

ax1.plot(x, np.sin(x))
ax1.set_title('Sine Wave - how2matplotlib.com')

ax2.plot(x, np.cos(x))
ax2.set_title('Cosine Wave - how2matplotlib.com')

ax3.plot(x, np.tan(x))
ax3.set_title('Tangent Wave - how2matplotlib.com')

ax4.plot(x, np.exp(x))
ax4.set_title('Exponential Function - how2matplotlib.com')

ax5.plot(x, np.log(x))
ax5.set_title('Logarithmic Function - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

subplot2grid允许我们指定每个子图的起始位置、跨度和大小,从而创建非常灵活的布局。

14. 创建具有不同比例的子图

有时我们可能需要在同一个图形中显示具有不同比例的数据:

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 1000 * np.sin(x)

ax1.plot(x, y1)
ax1.set_title('Small Scale Sine Wave - how2matplotlib.com')

ax2.plot(x, y2)
ax2.set_title('Large Scale Sine Wave - how2matplotlib.com')

# 设置不同的y轴范围
ax1.set_ylim(-1.5, 1.5)
ax2.set_ylim(-1500, 1500)

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了两个子图,一个显示小尺度的正弦波,另一个显示大尺度的正弦波。通过设置不同的y轴范围,我们可以在同一个图形中清晰地显示这两种不同尺度的数据。

15. 创建具有共享colorbar的子图

当我们有多个相关的图像或热图时,使用共享的colorbar可以使比较更加直观:

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# 创建两个相关但不同的数据集
data1 = np.random.rand(10, 10)
data2 = data1 + 0.1 * np.random.rand(10, 10)

# 绘制两个热图
im1 = ax1.imshow(data1, cmap='viridis')
im2 = ax2.imshow(data2, cmap='viridis')

ax1.set_title('Dataset 1 - how2matplotlib.com')
ax2.set_title('Dataset 2 - how2matplotlib.com')

# 添加共享的colorbar
fig.colorbar(im1, ax=[ax1, ax2], label='Value')

plt.tight_layout()
plt.show()

Output:

Matplotlib中plt.subplots的全面指南:创建灵活的子图布局

在这个例子中,我们创建了两个相关的数据集,并在两个子图中分别显示它们。通过添加一个共享的colorbar,我们可以直观地比较这两个数据集。

结论

plt.subplots是Matplotlib库中一个非常强大和灵活的工具,它允许我们创建各种复杂的图形布局。从简单的网格布局到复杂的嵌套布局,从2D图到3D图,从单一类型的图到混合不同类型的图,plt.subplots都能轻松应对。

通过本文的详细介绍和丰富的示例,我们探索了plt.subplots的多种用法和技巧。这些知识将帮助你更好地组织和展示你的数据,创建更加专业和吸引人的可视化效果。

记住,数据可视化不仅仅是展示数据,更是讲述数据背后的故事。通过灵活运用plt.subplots,你可以更有效地传达数据中的洞察和发现,让你的可视化作品更具说服力和影响力。

无论你是数据科学家、研究人员,还是任何需要进行数据可视化的专业人士,掌握plt.subplots都将极大地提升你的数据展示能力。继续探索和实践,你会发现Matplotlib和plt.subplots还有更多令人惊喜的功能等待你去发掘!

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程