Matplotlib.pyplot.subplot()函数:轻松创建多子图布局
参考:Matplotlib.pyplot.subplot() function in Python
Matplotlib是Python中最流行的数据可视化库之一,而pyplot.subplot()函数是其中一个强大而灵活的工具,用于创建多子图布局。本文将深入探讨pyplot.subplot()函数的用法、参数和各种应用场景,帮助您更好地掌握这个重要的可视化工具。
1. pyplot.subplot()函数简介
pyplot.subplot()函数是Matplotlib库中用于创建子图的核心函数之一。它允许您在一个图形窗口中创建多个子图,每个子图可以包含不同的数据可视化。这个函数的基本语法如下:
import matplotlib.pyplot as plt
plt.subplot(nrows, ncols, index)
其中:
– nrows:子图布局的行数
– ncols:子图布局的列数
– index:当前子图的索引(从1开始)
让我们看一个简单的例子:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.subplot(2, 1, 1)
plt.plot(x, y1)
plt.title('Sine Wave - how2matplotlib.com')
plt.subplot(2, 1, 2)
plt.plot(x, y2)
plt.title('Cosine Wave - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们创建了一个2行1列的子图布局。第一个子图显示正弦波,第二个子图显示余弦波。
2. subplot()函数的参数详解
pyplot.subplot()函数有几种不同的调用方式,让我们逐一探讨:
2.1 三个整数参数
最常见的调用方式是使用三个整数参数:
plt.subplot(nrows, ncols, index)
例如:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(2, 2, 1)
plt.plot(x, y)
plt.title('Subplot 1 - how2matplotlib.com')
plt.subplot(2, 2, 2)
plt.plot(x, y**2)
plt.title('Subplot 2 - how2matplotlib.com')
plt.subplot(2, 2, 3)
plt.plot(x, y**3)
plt.title('Subplot 3 - how2matplotlib.com')
plt.subplot(2, 2, 4)
plt.plot(x, y**4)
plt.title('Subplot 4 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子创建了一个2×2的子图布局,每个子图显示不同幂次的正弦函数。
2.2 三位数参数
另一种常见的调用方式是使用一个三位数的整数:
plt.subplot(abc)
其中:
– a:行数
– b:列数
– c:索引
例如:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(221)
plt.plot(x, y)
plt.title('Subplot 221 - how2matplotlib.com')
plt.subplot(222)
plt.plot(x, y**2)
plt.title('Subplot 222 - how2matplotlib.com')
plt.subplot(223)
plt.plot(x, y**3)
plt.title('Subplot 223 - how2matplotlib.com')
plt.subplot(224)
plt.plot(x, y**4)
plt.title('Subplot 224 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子的效果与前一个例子相同,但使用了更简洁的三位数参数形式。
2.3 SubplotSpec参数
subplot()函数还可以接受一个SubplotSpec对象作为参数,这允许更灵活的子图布局:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(2, 2)
plt.subplot(gs[0, 0])
plt.text(0.5, 0.5, 'Subplot 1 - how2matplotlib.com', ha='center', va='center')
plt.subplot(gs[0, 1])
plt.text(0.5, 0.5, 'Subplot 2 - how2matplotlib.com', ha='center', va='center')
plt.subplot(gs[1, :])
plt.text(0.5, 0.5, 'Subplot 3 (spans two columns) - how2matplotlib.com', ha='center', va='center')
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们使用GridSpec创建了一个更复杂的布局,其中第三个子图跨越了两列。
3. subplot()函数的高级用法
3.1 创建不规则子图布局
subplot()函数允许创建不规则的子图布局,例如:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(2, 3, 1)
plt.plot(x, y)
plt.title('Subplot 1 - how2matplotlib.com')
plt.subplot(2, 3, 2)
plt.plot(x, y**2)
plt.title('Subplot 2 - how2matplotlib.com')
plt.subplot(2, 3, 3)
plt.plot(x, y**3)
plt.title('Subplot 3 - how2matplotlib.com')
plt.subplot(2, 3, (4, 6))
plt.plot(x, y**4)
plt.title('Subplot 4-6 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
在这个例子中,最后一个子图跨越了底部的三个位置。
3.2 使用add_subplot()方法
除了pyplot.subplot()函数,我们还可以使用Figure对象的add_subplot()方法来创建子图:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax1 = fig.add_subplot(221)
ax1.plot(x, y)
ax1.set_title('Subplot 1 - how2matplotlib.com')
ax2 = fig.add_subplot(222)
ax2.plot(x, y**2)
ax2.set_title('Subplot 2 - how2matplotlib.com')
ax3 = fig.add_subplot(223)
ax3.plot(x, y**3)
ax3.set_title('Subplot 3 - how2matplotlib.com')
ax4 = fig.add_subplot(224)
ax4.plot(x, y**4)
ax4.set_title('Subplot 4 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这种方法的优点是它返回Axes对象,允许我们更精细地控制每个子图。
3.3 使用subplots()函数
对于简单的网格布局,我们可以使用pyplot.subplots()函数一次性创建多个子图:
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(2, 2)
x = np.linspace(0, 10, 100)
y = np.sin(x)
axs[0, 0].plot(x, y)
axs[0, 0].set_title('Subplot 1 - how2matplotlib.com')
axs[0, 1].plot(x, y**2)
axs[0, 1].set_title('Subplot 2 - how2matplotlib.com')
axs[1, 0].plot(x, y**3)
axs[1, 0].set_title('Subplot 3 - how2matplotlib.com')
axs[1, 1].plot(x, y**4)
axs[1, 1].set_title('Subplot 4 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个方法创建了一个2×2的子图网格,并返回一个Figure对象和一个Axes对象的二维数组。
4. 子图的样式和布局调整
4.1 调整子图间距
我们可以使用plt.subplots_adjust()函数来调整子图之间的间距:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(221)
plt.plot(x, y)
plt.title('Subplot 1 - how2matplotlib.com')
plt.subplot(222)
plt.plot(x, y**2)
plt.title('Subplot 2 - how2matplotlib.com')
plt.subplot(223)
plt.plot(x, y**3)
plt.title('Subplot 3 - how2matplotlib.com')
plt.subplot(224)
plt.plot(x, y**4)
plt.title('Subplot 4 - how2matplotlib.com')
plt.subplots_adjust(wspace=0.5, hspace=0.5)
plt.show()
Output:
在这个例子中,我们增加了子图之间的水平和垂直间距。
4.2 使用GridSpec进行精细布局
GridSpec允许我们创建更复杂和灵活的子图布局:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
gs = gridspec.GridSpec(3, 3)
ax1 = fig.add_subplot(gs[0, :])
ax1.text(0.5, 0.5, 'Subplot 1 - how2matplotlib.com', ha='center', va='center')
ax2 = fig.add_subplot(gs[1, :-1])
ax2.text(0.5, 0.5, 'Subplot 2 - how2matplotlib.com', ha='center', va='center')
ax3 = fig.add_subplot(gs[1:, -1])
ax3.text(0.5, 0.5, 'Subplot 3 - how2matplotlib.com', ha='center', va='center')
ax4 = fig.add_subplot(gs[-1, 0])
ax4.text(0.5, 0.5, 'Subplot 4 - how2matplotlib.com', ha='center', va='center')
ax5 = fig.add_subplot(gs[-1, -2])
ax5.text(0.5, 0.5, 'Subplot 5 - how2matplotlib.com', ha='center', va='center')
plt.tight_layout()
plt.show()
Output:
这个例子创建了一个复杂的布局,包括跨越多个网格单元的子图。
4.3 设置子图的宽高比
我们可以使用set_aspect()方法来设置子图的宽高比:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
ax1.plot(x, y)
ax1.set_title('Default Aspect Ratio - how2matplotlib.com')
ax2.plot(x, y)
ax2.set_aspect('equal')
ax2.set_title('Equal Aspect Ratio - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
在这个例子中,第二个子图被设置为等比例,这意味着x轴和y轴的单位长度相等。
5. 子图中的数据可视化技巧
5.1 在子图中绘制不同类型的图表
subplot()函数允许我们在不同的子图中绘制不同类型的图表:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(221)
plt.plot(x, y)
plt.title('Line Plot - how2matplotlib.com')
plt.subplot(222)
plt.scatter(x, y)
plt.title('Scatter Plot - how2matplotlib.com')
plt.subplot(223)
plt.bar(x[::10], y[::10])
plt.title('Bar Plot - how2matplotlib.com')
plt.subplot(224)
plt.hist(y, bins=20)
plt.title('Histogram - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子在四个子图中分别绘制了线图、散点图、柱状图和直方图。
5.2 在子图中添加图例
我们可以为每个子图添加图例:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.subplot(211)
plt.plot(x, y1, label='sin(x)')
plt.plot(x, y2, label='cos(x)')
plt.title('Trigonometric Functions - how2matplotlib.com')
plt.legend()
plt.subplot(212)
plt.plot(x, y1**2, label='sin^2(x)')
plt.plot(x, y2**2, label='cos^2(x)')
plt.title('Squared Trigonometric Functions - how2matplotlib.com')
plt.legend()
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们为每个子图添加了图例,显示了不同曲线的标签。
5.3 在子图中添加文本注释
我们可以使用text()方法在子图中添加文本注释:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.subplot(111)
plt.plot(x, y)
plt.title('Sine Wave with Annotations - how2matplotlib.com')
plt.text(np.pi/2, 1, 'Maximum', ha='center', va='bottom')
plt.text(3*np.pi/2, -1, 'Minimum', ha='center', va='top')plt.annotate('Zero crossing', xy=(np.pi, 0), xytext=(np.pi, 0.5),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.tight_layout()
plt.show()
这个例子在正弦波图上添加了文本注释和带箭头的标注。
6. 子图的共享轴
6.1 共享x轴或y轴
我们可以让多个子图共享x轴或y轴:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.plot(x, y1)
ax1.set_title('Sine Wave - how2matplotlib.com')
ax2.plot(x, y2)
ax2.set_title('Cosine Wave - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
在这个例子中,两个子图共享x轴,这意味着它们具有相同的x轴范围和刻度。
6.2 使用twinx()创建双y轴图
我们可以使用twinx()方法创建具有两个y轴的图:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(x/10)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('x')
ax1.set_ylabel('sin(x)', color=color)
ax1.plot(x, y1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # 创建共享x轴的第二个y轴
color = 'tab:blue'
ax2.set_ylabel('exp(x/10)', color=color)
ax2.plot(x, y2, color=color)
ax2.tick_params(axis='y', labelcolor=color)
plt.title('Two scales - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子创建了一个具有两个y轴的图,左侧y轴显示正弦函数,右侧y轴显示指数函数。
7. 子图中的3D绘图
Matplotlib还支持在子图中创建3D图形:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(12, 5))
# 3D surface plot
ax1 = fig.add_subplot(121, projection='3d')
x = np.arange(-5, 5, 0.25)
y = np.arange(-5, 5, 0.25)
x, y = np.meshgrid(x, y)
r = np.sqrt(x**2 + y**2)
z = np.sin(r)
surf = ax1.plot_surface(x, y, z, cmap='viridis')
ax1.set_title('3D Surface Plot - how2matplotlib.com')
# 3D scatter plot
ax2 = fig.add_subplot(122, projection='3d')
n = 100
xs = np.random.rand(n)
ys = np.random.rand(n)
zs = np.random.rand(n)
ax2.scatter(xs, ys, zs)
ax2.set_title('3D Scatter Plot - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子创建了两个3D子图:一个3D表面图和一个3D散点图。
8. 子图的动态调整
8.1 使用gridspec_kw调整子图大小
我们可以使用gridspec_kw参数来调整子图的相对大小:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [2, 1]})
ax1.plot(x, y)
ax1.set_title('Larger Subplot - how2matplotlib.com')
ax2.plot(x, y**2)
ax2.set_title('Smaller Subplot - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们创建了两个高度比为2:1的子图。
8.2 动态添加和删除子图
我们可以动态地添加和删除子图:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = plt.figure()
# 添加第一个子图
ax1 = fig.add_subplot(211)
ax1.plot(x, y)
ax1.set_title('First Subplot - how2matplotlib.com')
# 添加第二个子图
ax2 = fig.add_subplot(212)
ax2.plot(x, y**2)
ax2.set_title('Second Subplot - how2matplotlib.com')
plt.tight_layout()
plt.show()
# 删除第二个子图
fig.delaxes(ax2)
# 重新调整布局
plt.tight_layout()
plt.show()
这个例子首先创建了两个子图,然后删除了第二个子图。
9. 子图的样式定制
9.1 设置子图的背景色
我们可以为每个子图设置不同的背景色:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.plot(x, y)
ax1.set_title('Light Background - how2matplotlib.com')
ax1.set_facecolor('#f0f0f0')
ax2.plot(x, y)
ax2.set_title('Dark Background - how2matplotlib.com')
ax2.set_facecolor('#303030')
ax2.tick_params(colors='white')
ax2.title.set_color('white')
ax2.spines['bottom'].set_color('white')
ax2.spines['top'].set_color('white')
ax2.spines['right'].set_color('white')
ax2.spines['left'].set_color('white')
ax2.yaxis.label.set_color('white')
ax2.xaxis.label.set_color('white')
plt.tight_layout()
plt.show()
Output:
这个例子创建了两个子图,一个有浅色背景,另一个有深色背景。
9.2 自定义子图的网格线
我们可以为每个子图自定义网格线的样式:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
ax1.plot(x, y)
ax1.set_title('Default Grid - how2matplotlib.com')
ax1.grid(True)
ax2.plot(x, y)
ax2.set_title('Custom Grid - how2matplotlib.com')
ax2.grid(True, linestyle='--', color='r', alpha=0.5)
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何自定义子图的网格线样式。
10. 结论
Matplotlib的subplot()函数是一个强大而灵活的工具,允许我们在一个图形窗口中创建复杂的多子图布局。通过本文的详细介绍和丰富的示例,我们探讨了subplot()函数的基本用法、高级技巧以及与之相关的其他函数和方法。
从简单的网格布局到复杂的不规则布局,从2D图形到3D可视化,subplot()函数都能满足各种数据可视化需求。通过调整子图的大小、位置、样式和内容,我们可以创建出既美观又信息丰富的图表。
在实际应用中,合理使用subplot()函数可以帮助我们更有效地展示和比较多组数据,提高数据分析和展示的效率。无论是科学研究、数据分析还是商业报告,掌握subplot()函数都将极大地提升您的数据可视化能力。