2.4 特殊图形绘制 Matplotlib 进阶绘图:探索特殊图形绘制的奥秘 (2.4 特殊图形绘制) 在 Matplotlib 的广阔绘图世界中,除了常见的折线图、散点图和柱状图之外,还隐藏着许多功能强大的特殊图形,它们能够以独特的方式呈现数据,揭示数据背后的深层信息。本篇文章将深入 Matplotlib 进阶绘图领域的 2.4 特殊图形绘制 部分,带您探索这些不为人知的绘图技巧,并通过代码实践和详细解析,让您掌握这些高级绘图方法,为您的数据可视化工具箱增添新的利器。 2.4.1 轮廓图 (Contour Plots) 轮廓图是一种用于表示三维曲面在二维平面上的投影的图形。它通过一系列等高线来表示曲面在不同高度上的形状,常用于地理、气象、物理等领域,例如绘制地形图、等温线图等。
在 Matplotlib 的广阔绘图世界中,除了常见的折线图、散点图和柱状图之外,还隐藏着许多功能强大的特殊图形,它们能够以独特的方式呈现数据,揭示数据背后的深层信息。本篇文章将深入 Matplotlib 进阶绘图领域的 2.4 特殊图形绘制 部分,带您探索这些不为人知的绘图技巧,并通过代码实践和详细解析,让您掌握这些高级绘图方法,为您的数据可视化工具箱增添新的利器。
轮廓图是一种用于表示三维曲面在二维平面上的投影的图形。它通过一系列等高线来表示曲面在不同高度上的形状,常用于地理、气象、物理等领域,例如绘制地形图、等温线图等。在 Matplotlib 中,我们可以使用 contour 和 contourf 函数来绘制轮廓图。
import matplotlib.pyplot as plt import numpy as np # 创建网格数据 x = np.linspace(-3.0, 3.0, 100) y = np.linspace(-3.0, 3.0, 100) X, Y = np.meshgrid(x, y) Z = np.sqrt(X**2 + Y**2) # 定义高度函数 # 绘制轮廓线 CS = plt.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5) plt.clabel(CS, inline=True, fontsize=8) # 添加轮廓线标签 # 绘制填充轮廓 CF = plt.contourf(X, Y, Z, levels=20, cmap=plt.cm.viridis) plt.colorbar(CF) # 添加颜色条 plt.title('Contour Plot Example') plt.xlabel('X-axis') plt.ylabel('Y-axis') plt.show()
代码详解:
导入库: matplotlib.pyplot 用于绘图,numpy 用于生成数据。
创建网格数据:
np.linspace(-3.0, 3.0, 100) 创建 x 和 y 轴的坐标范围,从 -3.0 到 3.0,包含 100 个点。
np.meshgrid(x, y) 生成网格矩阵 X 和 Y,用于定义二维平面上的点。
Z = np.sqrt(X**2 + Y**2) 定义了高度函数,这里使用距离原点的距离作为高度值,形成一个圆锥形曲面。
绘制轮廓线:
plt.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5) 函数绘制轮廓线。
X, Y, Z:输入数据,分别表示 x 坐标、y 坐标和高度值。
levels=20:指定轮廓线的数量,这里设置为 20 条等高线。
colors='black':设置轮廓线颜色为黑色。
linewidths=0.5:设置轮廓线宽度为 0.5。
plt.clabel(CS, inline=True, fontsize=8):为轮廓线添加标签。
CS:plt.contour 函数的返回值,包含了轮廓线的信息。
inline=True:标签嵌入到轮廓线中。
fontsize=8:标签字体大小为 8。
绘制填充轮廓:
plt.contourf(X, Y, Z, levels=20, cmap=plt.cm.viridis) 函数绘制填充轮廓。
cmap=plt.cm.viridis:设置颜色映射,这里使用 viridis 色彩映射方案,色彩从紫色到黄色变化,代表高度的递增。plt.colorbar(CF):添加颜色条,显示颜色与高度值的对应关系。
添加标题和轴标签: plt.title, plt.xlabel, plt.ylabel 函数用于添加图形的标题和轴标签。
显示图形: plt.show() 函数显示绘制的图形。
我们可以通过调整 contour 和 contourf 函数的参数,进一步自定义轮廓图的样式和颜色。例如,我们可以使用不同的颜色映射方案 (cmap),自定义轮廓线的颜色 (colors),线型 (linestyles),线宽 (linewidths) 等。
# 自定义颜色映射和轮廓线样式 CF = plt.contourf(X, Y, Z, levels=np.arange(0, 4, 0.5), cmap=plt.cm.coolwarm) # 使用 coolwarm 色彩映射,并自定义 levels CS = plt.contour(X, Y, Z, levels=[1, 2, 3], colors='red', linestyles='dashed', linewidths=2) # 自定义特定高度的轮廓线样式 plt.clabel(CS, inline=True, fontsize=10) plt.colorbar(CF) plt.title('Customized Contour Plot') plt.show()
代码解释:
levels=np.arange(0, 4, 0.5):自定义轮廓线的高度级别,从 0 到 4,步长为 0.5。
cmap=plt.cm.coolwarm:使用 coolwarm 色彩映射方案,色彩从蓝色到红色变化。
levels=[1, 2, 3]:只绘制高度为 1, 2, 3 的轮廓线。
colors='red':设置特定轮廓线的颜色为红色。
linestyles='dashed':设置特定轮廓线的线型为虚线。
linewidths=2:设置特定轮廓线的线宽为 2。
矢量场图用于表示矢量场,即在二维或三维空间中,每个点都关联一个矢量的场。矢量场图常用于流体力学、电磁学等领域,例如绘制流场、磁场等。在 Matplotlib 中,我们可以使用 quiver 函数来绘制矢量场图。
import matplotlib.pyplot as plt import numpy as np # 创建网格数据 x = np.linspace(-5, 5, 10) y = np.linspace(-5, 5, 10) X, Y = np.meshgrid(x, y) # 定义矢量场 U = -Y # x 方向分量 V = X # y 方向分量 # 绘制矢量场图 plt.quiver(X, Y, U, V) plt.title('Quiver Plot Example') plt.xlabel('X-axis') plt.ylabel('Y-axis') plt.show()
代码详解:
创建网格数据: 与轮廓图类似,创建网格矩阵 X 和 Y。
定义矢量场:
U = -Y:定义 x 方向的矢量分量,这里设置为 -Y,即矢量的 x 分量与 y 坐标成反比。
V = X:定义 y 方向的矢量分量,这里设置为 X,即矢量 y 分量与 x 坐标成正比。
这样的定义会产生一个旋转的矢量场。
绘制矢量场图:
plt.quiver(X, Y, U, V) 函数绘制矢量场图。
X, Y:矢量箭头的起始位置坐标。
U, V:矢量在 x 和 y 方向的分量。
quiver 函数提供了丰富的参数来调整矢量箭头的样式和颜色,例如 scale 参数控制箭头长度,color 参数控制箭头颜色,width 参数控制箭头杆的宽度,headwidth、headlength、headaxislength 参数控制箭头头的形状等。
# 自定义矢量箭头样式和颜色 plt.quiver(X, Y, U, V, color='r', scale=50, width=0.01, headwidth=3, headlength=5) # 自定义箭头颜色、长度、宽度和头部样式 plt.title('Customized Quiver Plot') plt.show()
代码解释:
color='r':设置箭头颜色为红色 (red)。
scale=50:设置箭头长度的比例因子,值越大箭头越短。
width=0.01:设置箭头杆的宽度。
headwidth=3:设置箭头头的宽度。
headlength=5:设置箭头头的长度。
极坐标图是一种使用极坐标系来表示数据的图形。极坐标系使用角度 (\theta) 和半径 (r) 来定位点,与直角坐标系 (x, y) 不同。极坐标图常用于表示周期性数据、方向性数据等,例如雷达图、风玫瑰图等。在 Matplotlib 中,我们可以使用 polar 函数来绘制极坐标图。
import matplotlib.pyplot as plt import numpy as np # 创建角度和半径数据 theta = np.linspace(0, 2*np.pi, 100) # 角度范围 0 到 2π r = np.sin(3*theta) # 半径函数 # 创建极坐标子图 ax = plt.subplot(111, projection='polar') # 指定子图为极坐标投影 # 绘制极坐标曲线 ax.plot(theta, r) ax.set_title('Polar Plot Example') plt.show()
代码详解:
创建角度和半径数据:
theta = np.linspace(0, 2*np.pi, 100):创建角度数据,从 0 到 2π,包含 100 个点。
r = np.sin(3*theta):定义半径函数,这里使用 sin(3*theta),产生一个三叶玫瑰线。
创建极坐标子图:
ax = plt.subplot(111, projection='polar'):创建子图,并指定 projection='polar',将子图设置为极坐标投影。绘制极坐标曲线:
ax.plot(theta, r):使用 ax.plot 函数在极坐标子图上绘制曲线,输入参数为角度 theta 和半径 r。设置标题: ax.set_title 函数用于设置极坐标图的标题。
我们可以使用 ax.set_theta_direction,ax.set_theta_offset,ax.set_rlim,ax.set_rticks 等函数来自定义极坐标轴的刻度、方向、范围等。还可以使用 ax.grid(True) 来显示极坐标网格。
# 自定义极坐标轴和网格 ax = plt.subplot(111, projection='polar') ax.plot(theta, r) ax.set_theta_direction(-1) # 设置角度方向为顺时针,默认逆时针 ax.set_theta_offset(np.pi/2) # 设置角度偏移 π/2,起始角度从 y 轴正方向开始 ax.set_rlim(0, 1) # 设置半径轴范围为 0 到 1 ax.set_rticks([0.2, 0.4, 0.6, 0.8, 1.0]) # 自定义半径轴刻度 ax.grid(True) # 显示极坐标网格 ax.set_title('Customized Polar Plot') plt.show()
代码解释:
ax.set_theta_direction(-1):设置角度方向为顺时针 (-1),默认逆时针 (1)。
ax.set_theta_offset(np.pi/2):设置角度偏移 π/2,起始角度从 y 轴正方向开始 (默认 x 轴正方向)。
ax.set_rlim(0, 1):设置半径轴范围为 0 到 1。
ax.set_rticks([0.2, 0.4, 0.6, 0.8, 1.0]):自定义半径轴刻度,只显示指定的刻度值。
ax.grid(True):显示极坐标网格。
Matplotlib 也可以绘制三维图形,包括 3D 散点图、3D 曲面图、3D 柱状图等。绘制 3D 图形需要导入 mpl_toolkits.mplot3d 工具包。
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 导入 3D 绘图工具包 import numpy as np # 创建 3D 子图 fig = plt.figure() ax = fig.add_subplot(projection='3d') # 添加 3D 子图 # 生成 3D 散点数据 z = np.linspace(0, 15, 100) x = np.sin(z) y = np.cos(z) # 绘制 3D 散点图 ax.scatter(x, y, z) ax.set_title('3D Scatter Plot Example') ax.set_xlabel('X-axis') ax.set_ylabel('Y-axis') ax.set_zlabel('Z-axis') plt.show()
代码详解:
导入 3D 绘图工具包: from mpl_toolkits.mplot3d import Axes3D 导入 Axes3D 类,用于创建 3D 坐标轴。
创建 3D 子图:
fig = plt.figure():创建 Figure 对象。
ax = fig.add_subplot(projection='3d'):在 Figure 对象中添加一个子图,并指定 projection='3d',将子图设置为 3D 投影。
生成 3D 散点数据:
z = np.linspace(0, 15, 100):生成 z 轴数据。
x = np.sin(z),y = np.cos(z):根据 z 轴数据生成 x 和 y 轴数据,形成一个螺旋线形状的散点分布。
绘制 3D 散点图:
ax.scatter(x, y, z):使用 ax.scatter 函数绘制 3D 散点图,输入参数为 x, y, z 坐标。设置轴标签: ax.set_xlabel, ax.set_ylabel, ax.set_zlabel 函数用于设置 3D 图形的 x, y, z 轴标签。
除了散点图,我们还可以使用 plot_surface 和 plot_wireframe 函数绘制 3D 曲面图和线框图。
# 绘制 3D 曲面图和线框图 fig = plt.figure(figsize=(12, 6)) # 设置 figure 大小 # 3D 曲面图 ax1 = fig.add_subplot(121, projection='3d') # 创建第一个子图 X, Y = np.meshgrid(np.arange(-5, 5, 0.25), np.arange(-5, 5, 0.25)) Z = np.sin(np.sqrt(X**2 + Y**2)) surf = ax1.plot_surface(X, Y, Z, cmap=plt.cm.coolwarm) # 绘制曲面图,使用 coolwarm 色彩映射 fig.colorbar(surf, shrink=0.5, aspect=10, ax=ax1) # 添加颜色条到第一个子图 ax1.set_title('3D Surface Plot') # 3D 线框图 ax2 = fig.add_subplot(122, projection='3d') # 创建第二个子图 wireframe = ax2.plot_wireframe(X, Y, Z, color='black') # 绘制线框图,颜色为黑色 ax2.set_title('3D Wireframe Plot') plt.show()
代码解释:
创建 Figure 和子图: 使用 fig.add_subplot(121, projection='3d') 和 fig.add_subplot(122, projection='3d') 创建两个并排的 3D 子图。
生成曲面数据: 使用 np.meshgrid 创建网格数据 X 和 Y,并定义高度函数 Z = np.sin(np.sqrt(X**2 + Y**2))。
绘制 3D 曲面图:
ax1.plot_surface(X, Y, Z, cmap=plt.cm.coolwarm):使用 plot_surface 函数绘制 3D 曲面图。
fig.colorbar(surf, shrink=0.5, aspect=10, ax=ax1):为曲面图添加颜色条。
绘制 3D 线框图:
ax2.plot_wireframe(X, Y, Z, color='black'):使用 plot_wireframe 函数绘制 3D 线框图。阶梯图 (Step Plot) 和棉棒图 (Stem Plot) 都是用于表示离散数据的图形。阶梯图用水平线段连接数据点,形成阶梯状的图形,常用于表示累积分布函数等。棉棒图用垂直线段表示数据点的值,并在底部添加一个圆点,形如棉棒,常用于表示脉冲信号、离散序列等。在 Matplotlib 中,我们可以使用 step 和 stem 函数分别绘制阶梯图和棉棒图。
import matplotlib.pyplot as plt import numpy as np # 生成数据 x = np.arange(0, 10, 1) y = np.random.rand(10) # 绘制阶梯图 plt.step(x, y, where='post') # where 参数控制阶梯的位置,'post' 表示阶梯在 x 值之后 # 绘制棉棒图 plt.stem(x, y, use_line_collection=True) # use_line_collection 参数提高性能 plt.title('Step and Stem Plot Example') plt.xlabel('X-axis') plt.ylabel('Y-axis') plt.show()
代码详解:
生成数据: x = np.arange(0, 10, 1) 生成 x 轴数据,y = np.random.rand(10) 生成 y 轴数据,模拟离散数据。
绘制阶梯图:
plt.step(x, y, where='post') 函数绘制阶梯图。
where='post':设置阶梯的位置,'post' 表示阶梯在 x 值之后,即水平线段从 x 值开始延伸。'pre' 表示阶梯在 x 值之前,'mid' 表示阶梯在 x 值中间。绘制棉棒图:
plt.stem(x, y, use_line_collection=True) 函数绘制棉棒图。
use_line_collection=True:使用 LineCollection 对象来绘制棉棒图,可以提高性能,尤其是在数据量较大时。我们可以自定义阶梯图的线型、颜色、填充颜色等,以及棉棒图的线条样式、颜色、标记样式等。
# 自定义阶梯图和棉棒图样式 plt.figure(figsize=(10, 5)) # 设置 figure 大小 # 自定义阶梯图 plt.subplot(121) # 创建第一个子图 plt.step(x, y, color='green', linestyle='--', linewidth=2, fillstyle='full', where='mid', label='Step Data') # 自定义阶梯图样式 plt.fill_between(x, y, step='mid', alpha=0.3, color='green') # 填充阶梯图下方区域 plt.legend() plt.title('Customized Step Plot') # 自定义棉棒图 plt.subplot(122) # 创建第二个子图 plt.stem(x, y, linefmt='r-', markerfmt='ro', basefmt='b-', use_line_collection=True, label='Stem Data') # 自定义棉棒图样式 plt.legend() plt.title('Customized Stem Plot') plt.show()
代码解释:
自定义阶梯图:
color='green',linestyle='--',linewidth=2:自定义阶梯线颜色、线型和线宽。
fillstyle='full':设置填充样式为实心。
where='mid':设置阶梯位置为 'mid'。
label='Step Data':设置图例标签。
plt.fill_between(x, y, step='mid', alpha=0.3, color='green'):填充阶梯图下方区域,step='mid' 确保填充区域与阶梯对齐,alpha=0.3 设置透明度,color='green' 设置填充颜色。
自定义棉棒图:
linefmt='r-':设置棉棒线条格式为红色实线。
markerfmt='ro':设置棉棒标记格式为红色圆圈。
basefmt='b-':设置基线格式为蓝色实线。
label='Stem Data':设置图例标签。
箱线图 (Box Plot) 和提琴图 (Violin Plot) 都是用于可视化数据分布的图形。箱线图通过箱子、须线和离群点来简洁地展示数据的中位数、四分位数、极值和异常值,常用于比较不同组数据的分布特征。提琴图结合了箱线图和核密度估计,更详细地展示数据的分布形状,形如提琴,可以更直观地比较不同组数据的分布差异。在 Matplotlib 中,我们可以使用 boxplot 和 violinplot 函数分别绘制箱线图和提琴图。
import matplotlib.pyplot as plt import numpy as np # 生成多组数据 data = [np.random.normal(0, std, 100) for std in range(1, 4)] # 生成三组正态分布数据,标准差分别为 1, 2, 3 # 绘制箱线图 plt.boxplot(data) # 绘制提琴图 plt.violinplot(data) plt.title('Box and Violin Plot Example') plt.xlabel('Groups') plt.ylabel('Values') plt.show()
代码详解:
生成多组数据: data = [np.random.normal(0, std, 100) for std in range(1, 4)] 生成一个包含三组数据的列表,每组数据都是从正态分布中随机抽取的 100 个样本,标准差分别为 1, 2, 3。
绘制箱线图: plt.boxplot(data) 函数绘制箱线图,输入参数为数据列表 data。
绘制提琴图: plt.violinplot(data) 函数绘制提琴图,输入参数为数据列表 data。
我们可以自定义箱线图的箱体颜色、须线样式、离群点样式等,以及提琴图的提琴主体颜色、边缘线样式、中位数标记样式等。
# 自定义箱线图和提琴图样式 plt.figure(figsize=(12, 6)) # 设置 figure 大小 # 自定义箱线图 plt.subplot(121) # 创建第一个子图 boxprops = dict(linestyle='-', linewidth=2, color='blue') # 箱体样式 medianprops = dict(linestyle='-', linewidth=2, color='red') # 中位数线样式 whiskerprops = dict(linestyle='--', linewidth=1, color='green') # 须线样式 capprops = dict(linestyle='-', linewidth=1, color='purple') # 箱须端帽样式 flierprops = dict(marker='o', markerfacecolor='cyan', markersize=8, linestyle='none') # 离群点样式 plt.boxplot(data, boxprops=boxprops, medianprops=medianprops, whiskerprops=whiskerprops, capprops=capprops, flierprops=flierprops, labels=['Group 1', 'Group 2', 'Group 3']) # 自定义箱线图样式,并添加组标签 plt.title('Customized Box Plot') # 自定义提琴图 plt.subplot(122) # 创建第二个子图 parts = plt.violinplot(data, showmeans=False, showmedians=True, showextrema=True, widths=0.7, points=100, bw_method='scott', positions=[1, 2, 3]) # 自定义提琴图样式 for pc in parts['bodies']: # 遍历提琴主体 pc.set_facecolor('orange') # 设置提琴主体颜色 pc.set_edgecolor('black') # 设置提琴边缘颜色 pc.set_alpha(0.7) # 设置提琴透明度 parts['cmedians'].set_edgecolor('red') # 设置中位数标记颜色 plt.xticks([1, 2, 3], ['Group 1', 'Group 2', 'Group 3']) # 设置 x 轴刻度标签 plt.title('Customized Violin Plot') plt.show()
代码解释:
自定义箱线图:
使用字典 boxprops, medianprops, whiskerprops, capprops, flierprops 分别定义箱体、中位数线、须线、箱须端帽和离群点的样式。
将这些字典作为参数传递给 plt.boxplot 函数。