绘制子图(subplots)是在Matplotlib中创建多个子图的常见任务。通过子图,您可以将多个图形放置在同一图表中,以便比较不同的数据或可视化多个相关的图形。一般流程如下:
- 创建图形对象:首先,您需要创建一个图形对象,可以使用
plt.figure()
函数来完成。该图形对象代表整个图形窗口,您可以在其中放置多个子图。 - 添加子图:使用
fig.add_subplot()
函数来添加子图。这个函数接受三个参数,分别是行数、列数和子图的索引位置。例如,fig.add_subplot(2, 2, 1)
表示将创建一个2x2的网格,并在第一个位置创建子图。 - 绘制图表:在每个子图中,您可以使用Matplotlib的绘图函数(如
plot()
、scatter()
、bar()
等)来绘制不同类型的图表。 - 子图属性设置:您可以设置每个子图的标题、坐标轴标签、背景颜色、图例等属性,以使其更具可读性和吸引力。
- 调整子图布局:Matplotlib允许您调整子图之间的间距,以便更好地组织和排列它们。可以使用
plt.subplots_adjust()
函数来完成这个任务。 - 显示图形:一旦您创建并设置了所有子图,使用
plt.show()
函数来显示整个图形。
1 基本子图绘制示例
首先,让我们看一个基本的子图绘制示例。使用plt.subplots()
函数,您可以创建一个包含多个子图的图表,并将这些子图放置在一个网格中。以下是一个基本的示例:
import matplotlib.pyplot as plt import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y1 = np.sin(x) y2 = np.cos(x) # 创建一个包含两个子图的图表 fig, axes = plt.subplots(nrows=1, ncols=2) # 在第一个子图中绘制正弦函数 axes[0].plot(x, y1, label='Sine Function', color='blue') axes[0].set_title('Sine Function') # 在第二个子图中绘制余弦函数 axes[1].plot(x, y2, label='Cosine Function', color='red') axes[1].set_title('Cosine Function') # 显示图例 axes[0].legend() axes[1].legend() # 显示图形 plt.show()
运行:
以上代码演示了如何使用Matplotlib创建一个包含两个子图的图表。这两个子图分别显示了正弦函数和余弦函数的曲线。
- 导入Matplotlib库和NumPy库。
- 创建示例数据,使用NumPy的linspace函数生成0到2π之间的100个点作为x轴数据,同时计算对应的正弦值和余弦值作为y轴数据。
- 使用plt.subplots函数创建一个图表和一个由子图对象组成的数组。其中nrows=1表示创建一个行数为1,列数为2的图表。
- 在第一个子图中绘制正弦函数曲线,使用plot函数,并指定标签(label)和颜色(color)。同时设置标题(set_title)为"Sine Function"。
- 在第二个子图中绘制余弦函数曲线,同样使用plot函数,并指定标签和颜色。设置标题为"Cosine Function"。
- 显示图例,使用legend函数,在每个子图中显示曲线的标签。
- 最后调用plt.show()来显示图形。
2 子图网格布局
Matplotlib还允许您以更复杂的方式布局子图,以满足您的需求。您可以使用
gridspec
模块来实现更灵活的子图布局。以下是一个示例,演示如何使用gridspec
创建子图网格:
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y1 = np.sin(x) y2 = np.cos(x) y3 = np.tan(x) # 创建一个包含多个子图的图表,使用gridspec定义子图布局 fig = plt.figure(figsize=(10, 4)) gs = gridspec.GridSpec(1, 3) # 1行3列的子图布局 # 第一个子图 ax1 = plt.subplot(gs[0, 0]) ax1.plot(x, y1, label='Sine Function', color='blue') ax1.set_title('Sine Function') ax1.legend() # 第二个子图 ax2 = plt.subplot(gs[0, 1]) ax2.plot(x, y2, label='Cosine Function', color='red') ax2.set_title('Cosine Function') ax2.legend() # 第三个子图 ax3 = plt.subplot(gs[0, 2]) ax3.plot(x, y3, label='Tangent Function', color='green') ax3.set_title('Tangent Function') ax3.legend() # 调整子图之间的距离 plt.tight_layout() # 显示图形 plt.show()
运行:
这个示例创建了一个包含三个子图的图表,使用gridspec
模块定义了子图的布局。每个子图包含不同的三角函数,并具有自己的标题和图例。
- 导入Matplotlib库和NumPy库。
- 创建示例数据,使用NumPy的linspace函数生成0到2π之间的100个点作为x轴数据,同时计算对应的正弦、余弦和正切值作为y轴数据。
- 创建一个Figure对象,设置图表的大小为(10, 4)。
- 使用gridspec.GridSpec函数创建一个网格布局,指定1行3列的子图布局。
- 在第一个子图(ax1)中绘制正弦函数曲线,使用plot函数,并指定标签(label)和颜色(color)。同时设置标题(set_title)为"Sine Function"并显示图例(legend)。
- 在第二个子图(ax2)中绘制余弦函数曲线,同样使用plot函数,并指定标签和颜色。设置标题为"Cosine Function"并显示图例。
- 在第三个子图(ax3)中绘制正切函数曲线,同样使用plot函数,并指定标签和颜色。设置标题为"Tangent Function"并显示图例。
- 调用plt.tight_layout()函数来自动调整子图之间的距离。
- 最后调用plt.show()来显示图形。
3 调整子图的尺寸
以下是一些常用的参数,用于调整子图的尺寸和位置:
nrows
和ncols
:这两个参数用于指定子图的网格布局的行数和列数。例如,fig.add_subplot(2, 2, 1)
表示一个2x2的网格布局,其中有4个子图。- index:该参数指定子图在网格中的位置。例如,fig.add_subplot(2, 2, 1)表示在2x2的网格中的第一个位置创建子图。
- position:通过position参数,您可以设置子图的位置和大小,它是一个四元组,表示子图的左、下、宽度和高度。例如,fig.add_subplot(position=[0.1, 0.1, 0.8, 0.8])表示在图形中创建一个左上角偏移10%并且宽度和高度都为80%的子图。
projection
:用于指定子图的投影类型,例如3D子图、极坐标子图等。polar
:一个布尔值,用于指定子图是否使用极坐标。默认为False。
您可以通过设置gridspec
中每个子图的相对宽度来调整子图的尺寸。以下示例将第一个子图的宽度设置为其他两个子图的两倍:
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y1 = np.sin(x) y2 = np.cos(x) y3 = np.tan(x) # 创建一个包含多个子图的图表,使用gridspec定义子图布局 fig = plt.figure(figsize=(12, 4)) # 1行3列的子图布局,第一个子图宽度为其他两个的两倍 gs = gridspec.GridSpec(1, 3, width_ratios=[2, 1, 1]) # 第一个子图 ax1 = plt.subplot(gs[0, 0]) ax1.plot(x, y1, label='Sine Function', color='blue') ax1.set_title('Sine Function') ax1.legend() # 第二个子图 ax2 = plt.subplot(gs[0, 1]) ax2.plot(x, y2, label='Cosine Function', color='red') ax2.set_title('Cosine Function') ax2.legend() # 第三个子图 ax3 = plt.subplot(gs[0, 2]) ax3.plot(x, y3, label='Tangent Function', color='green') ax3.set_title('Tangent Function') ax3.legend() # 调整子图之间的距离 plt.tight_layout() # 显示图形 plt.show()
以上代码演示了如何使用Matplotlib创建一个包含多个子图的图表,并使用gridspec来定义子图布局。代码的步骤如下:
- 导入Matplotlib库和NumPy库。
- 创建示例数据,使用NumPy的linspace函数生成0到2π之间的100个点作为x轴数据,同时计算对应的正弦、余弦和正切值作为y轴数据。
- 创建一个Figure对象,设置图表的大小为(12, 4)。
- 使用gridspec.GridSpec函数创建一个网格布局,指定1行3列的子图布局,并通过width_ratios参数设置第一个子图的宽度为其他两个子图的两倍。
- 在第一个子图(ax1)中绘制正弦函数曲线,使用plot函数,并指定标签(label)和颜色(color)。同时设置标题(set_title)为"Sine Function"并显示图例(legend)。
- 在第二个子图(ax2)中绘制余弦函数曲线,同样使用plot函数,并指定标签和颜色。设置标题为"Cosine Function"并显示图例。
- 在第三个子图(ax3)中绘制正切函数曲线,同样使用plot函数,并指定标签和颜色。设置标题为"Tangent Function"并显示图例。
- 调用plt.tight_layout()函数来自动调整子图之间的距离。
- 最后调用plt.show()来显示图形。
4 多行多列的子图布局
您可以使用gridspec
创建多行多列的子图布局,以便在一个图表中组织更多的子图。以下示例演示了一个包含多行多列子图的图表:
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y = np.sin(x) # 创建一个包含多行多列子图的图表,使用gridspec定义子图布局 fig = plt.figure(figsize=(10, 6)) gs = gridspec.GridSpec(3, 2) # 3行2列的子图布局 # 绘制多行多列的子图 for i in range(3): for j in range(2): ax = plt.subplot(gs[i, j]) ax.plot(x, y, label='Sine Function', color='blue') ax.set_title(f'Subplot ({i+1}, {j+1})') ax.legend() # 调整子图之间的距离 plt.tight_layout() # 显示图形 plt.show()
运行:
5 子图之间的共享轴
您可以通过设置sharex
和sharey
参数来共享子图之间的X轴或Y轴。以下示例演示了在子图之间共享X轴的情况:
import matplotlib.pyplot as plt import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y1 = np.sin(x) y2 = np.cos(x) # 创建一个包含多个子图的图表 fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(8, 6)) # 第一个子图,共享X轴 ax1.plot(x, y1, label='Sine Function', color='blue') ax1.set_title('Shared X-Axis') ax1.legend() # 第二个子图,共享X轴 ax2.plot(x, y2, label='Cosine Function', color='red') ax2.legend() # 调整子图之间的距离 plt.tight_layout() # 显示图形 plt.show()
运行:
共享Y轴示例:
在这个示例中,我们创建了两个子图,通过
sharey=True
参数来共享Y轴。这两个子图分别绘制了sin函数和cos函数,并共享相同的Y轴刻度。整体标题用suptitle
函数添加。这个示例演示了如何创建共享Y轴的子图。代码如下:
import matplotlib.pyplot as plt import numpy as np # 创建示例数据 x = np.linspace(0, 10, 100) y1 = np.sin(x) y2 = np.cos(x) # 创建两个子图,共享Y轴 fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, figsize=(10, 4)) # 在第一个子图上绘制sin函数 ax1.plot(x, y1, label='Sine Function', color='blue', linestyle='--') ax1.set_title('Subplot 1: Sine Function') ax1.set_xlabel('X-axis') ax1.set_ylabel('Y-axis') ax1.legend() # 在第二个子图上绘制cos函数 ax2.plot(x, y2, label='Cosine Function', color='red', linestyle='-') ax2.set_title('Subplot 2: Cosine Function') ax2.set_xlabel('X-axis') ax2.legend() # 添加整体标题 plt.suptitle('Two Subplots Sharing Y-Axis', fontsize=16, fontweight='bold') # 显示图形 plt.show()
运行:
6 绘制多个子图类型
您可以在同一个图表中组合不同类型的子图,例如线图和散点图。以下示例演示了如何在同一图表
中绘制多个子图类型:
import matplotlib.pyplot as plt import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y1 = np.sin(x) y2 = np.cos(x) x_scatter = np.random.rand(50) * 2 * np.pi y_scatter = np.sin(x_scatter) # 创建一个包含多个子图的图表 fig, axs = plt.subplots(2, 2, figsize=(10, 6)) # 第一个子图:线图 axs[0, 0].plot(x, y1, label='Sine Function', color='blue') axs[0, 0].set_title('Line Plot') axs[0, 0].legend() # 第二个子图:散点图 axs[0, 1].scatter(x_scatter, y_scatter, label='Scatter Points', color='red', marker='o') axs[0, 1].set_title('Scatter Plot') axs[0, 1].legend() # 第三个子图:线图 axs[1, 0].plot(x, y2, label='Cosine Function', color='green') axs[1, 0].set_title('Line Plot') axs[1, 0].legend() # 第四个子图:散点图 axs[1, 1].scatter(x_scatter, y_scatter, label='Scatter Points', color='purple', marker='s') axs[1, 1].set_title('Scatter Plot') axs[1, 1].legend() # 调整子图之间的距离 plt.tight_layout() # 显示图形 plt.show()
运行:
- 导入Matplotlib库和NumPy库。
- 创建示例数据,使用NumPy的linspace函数生成0到2π之间的100个点作为x轴数据,并计算对应的正弦值和余弦值作为y轴数据。还生成了50个随机点用于绘制散点图。
- 创建一个包含2行2列子图的图表,使用
subplots
函数并设置figsize
参数指定图表的大小。subplots
函数会返回一个Figure对象和一个包含子图的Axes对象的二维数组。 - 在第一个子图(axs[0, 0])中绘制正弦函数的线图,使用
plot
函数,并指定标签(label)和颜色(color)。设置标题(set_title)为"Line Plot"并显示图例(legend)。 - 在第二个子图(axs[0, 1])中绘制散点图,使用
scatter
函数,并指定标签、颜色和标记(marker)类型。同样设置标题和图例。 - 在第三个子图(axs[1, 0])中绘制余弦函数的线图,使用
plot
函数,并指定标签和颜色。设置标题和图例。 - 在第四个子图(axs[1, 1])中绘制散点图,使用
scatter
函数,并指定标签、颜色和标记类型。同样设置标题和图例。 - 使用
tight_layout
函数调整子图之间的距离,使其更美观。 - 调用
show
函数显示图形。
7 实战:
绘制一个大图,里面包含6个不同类别的子图,不均匀布局。
第一行放一个子图,第二行放两个子图 ,第三行放三个子图 ,分别自适应设置子图的尺寸和背景色,示例与代码如下:
import matplotlib.pyplot as plt import numpy as np # 创建示例数据 x = np.linspace(0, 2 * np.pi, 100) y = np.sin(x) # 创建图形 fig = plt.figure(figsize=(12, 8)) # 在上方添加母图标题 fig.suptitle('Customized Subplots Example', fontsize=16, fontweight='bold') # fig.suptitle('Customized Subplots Example', fontsize=16, fontweight='bold', y=0.05) # 在下方添加母图标题 # 调整子图的布局,增加垂直间距,避免子图之间有交叉 plt.subplots_adjust(hspace=0.5) # 第一行,一个子图,绘制线图 ax1 = fig.add_subplot(3, 1, 1) ax1.plot(x, y, color='blue', label='Sine Function', linewidth=2, linestyle='--', marker='o', markersize=5) ax1.set_title('Line Plot', fontsize=14) ax1.set_facecolor('lightgray') ax1.set_xlabel('X-axis', fontsize=12) ax1.set_ylabel('Y-axis', fontsize=12) ax1.legend() # 添加注释 ax1.annotate('Peak Point', xy=(np.pi/2, 1), xytext=(np.pi/2, 1.2), arrowprops=dict(facecolor='black', shrink=0.05), fontsize=12, bbox=dict(boxstyle='round,pad=0.3', edgecolor='black', facecolor='yellow')) # 第二行,两个子图,一个散点图,一个柱状图 ax2 = fig.add_subplot(3, 2, 3) ax2.scatter(x, y, color='red', label='Scatter Plot', s=20) ax2.set_title('Scatter Plot', fontsize=14) ax2.set_facecolor('lightyellow') ax2.set_xlabel('X-axis', fontsize=12) ax2.set_ylabel('Y-axis', fontsize=12) ax2.legend() ax3 = fig.add_subplot(3, 2, 4) ax3.bar(x, y, color='green', label='Bar Plot', alpha=0.7) ax3.set_title('Bar Plot', fontsize=14) ax3.set_facecolor('lightgreen') ax3.set_xlabel('X-axis', fontsize=12) ax3.set_ylabel('Y-axis', fontsize=12) ax3.legend() # 第三行,三个子图,一个直方图,一个饼图,一个箱线图 ax4 = fig.add_subplot(3, 3, 7) ax4.hist(y, bins=20, color='purple', label='Histogram', alpha=0.7) ax4.set_title('Histogram', fontsize=14) ax4.set_facecolor('lightpink') ax4.set_xlabel('X-axis', fontsize=12) ax4.set_ylabel('Frequency', fontsize=12) ax4.legend() ax5 = fig.add_subplot(3, 3, 8) ax5.pie([len(y[y > 0]), len(y[y < 0])], labels=['Positive', 'Negative'], colors=['orange', 'lightblue'], autopct='%1.1f%%') ax5.set_title('Pie Chart', fontsize=14) ax5.set_facecolor('lightcoral') ax5.legend() ax6 = fig.add_subplot(3, 3, 9) ax6.boxplot(y, vert=False, widths=0.3, patch_artist=True, boxprops=dict(facecolor='lightgray')) ax6.set_title('Box Plot', fontsize=14) ax6.set_facecolor('lightblue') ax6.set_xlabel('X-axis', fontsize=12) ax6.legend([]) # 添加空的图例以解决警告 # 调整子图布局 plt.tight_layout() # 显示图形 plt.show()
运行:
上面的示例代码演示了如何创建一个包含不同类型子图的图形,并对每个子图进行了定制化设置。代码流程:
- 创建示例数据:使用
numpy
生成示例数据,这里生成了一个sin函数的数据。 - 创建图形对象:使用
plt.figure()
创建一个图形对象,可以设置图形的大小。 - 添加母图标题:使用
fig.suptitle()
可以为整个图形添加一个标题。 - 调整子图的布局:使用
plt.subplots_adjust()
可以调整子图之间的间距,这里增加了垂直间距。 - 创建子图:使用
fig.add_subplot()
创建子图,指定子图的位置和数量。 - 绘制不同类型的子图:根据需要,创建不同类型的子图,如线图、散点图、柱状图、直方图、饼图、箱线图等。
- 设置子图的标题、背景色、坐标轴标签和图例:使用
set_title()
、set_facecolor()
、set_xlabel()
、set_ylabel()
和legend()
方法来设置子图的各种属性。 - 添加注释:使用
annotate()
方法可以在子图上添加注释。 - 调整子图布局:使用
plt.tight_layout()
可以自动调整子图的布局,使其适应图形大小。 - 显示图形:使用
plt.show()
显示最终的图形。
这个示例演示了如何在一个图形中创建多个子图,并对每个子图进行不同的设置和绘制不同类型的图表。