文章目录
写在前面
不知道看到这篇博客的小伙伴是遇到什么问题才来看我这边篇博客,为了不浪费大家的时间,博主先简单介绍一下为什么要写这篇博客。
博主最近在画图,但是遇到一个问题,就是相似的图要画很多遍,可能就只是稍微改几个参数,几行代码,这样子写几个方法的话代码重复率太高了,于是乎博主想写一个万能的画图代码,该代码只需要完成基本参数的设置,其他的无需改动,可以实现自动画图。
为了实现该想法,我们就必须要知道画图需要提供什么,所以本篇博客将会先介绍plt的一些基本用法,了解这些用法之后再将其转化为我们的目标代码。
一、图形整体设置
通过 plt.figure() 或 plt.subplots() 设置全局参数。
(一)单图设置
- figsize: 图形尺寸,单位英寸
plt.figure(figsize=(8, 4)) # 宽度8英寸,高度4英寸
- dpi: 分辨率(每英寸像素数)
plt.figure(dpi=100) # 默认分辨率
- facecolor/edgecolor: 图形背景和边框颜色
plt.figure(facecolor='lightgray', edgecolor='black')
(二)子图设置
使用 plt.subplots() 创建多个子图,并通过返回的 axes 对象控制每个子图的参数。
通过 plt.subplots() 的参数设置整体属性:
fig, axes = plt.subplots(
nrows=2,
ncols=2,
figsize=(10, 8), # 图形尺寸
facecolor='lightgray', # 背景色
dpi=100, # 分辨率
sharex=True, # 共享 X 轴
sharey=True, # 共享 Y 轴
subplot_kw={'projection': ccrs.PlateCarree()} # 子图专用参数(如地图投影)
)
- 单个子图的参数设置
通过 axes 对象逐个设置属性:
# 设置第一个子图
axes[0,0].plot(x, y, color='red', linewidth=2, marker='o')
axes[0,0].set_title("Subplot 1", fontsize=12, color='blue')
axes[0,0].set_xlabel("X Axis", fontsize=10)
axes[0,0].set_ylabel("Y Axis", fontsize=10)
axes[0,0].grid(True, linestyle='--', alpha=0.5)
axes[0,0].tick_params(axis='x', rotation=45) # 旋转 X 轴刻度
- 坐标轴范围与刻度
单图:plt.xlim(0, 10)
子图:
axes[0,0].set_xlim(0, 10) # 设置 X 轴范围
axes[0,0].set_xticks([0, 5, 10]) # 设置刻度位置
axes[0,0].set_xticklabels(['Start', 'Mid', 'End']) # 设置刻度标签
- 图例与颜色条
单图:plt.legend(), plt.colorbar()
子图:
# 添加图例
axes[0,0].plot(x, y, label="Data")
axes[0,0].legend(loc='upper right', fontsize=8)
# 添加颜色条(需关联到绘图对象)
contour = axes[1,0].contourf(x_grid, y_grid, data, cmap='viridis')
fig.colorbar(contour, ax=axes[1,0], label='Values') # 指定关联的子图
- 子图展开
二维的子图也可以通过flatten展开为一维的形式,这样进行一个一个画图的时候比较方便。
axes = axes.flatten()
- 展开后的遍历方式:axes[i]
- 展开前的遍历方式:axes[i, j]
二、线条样式参数(适用于折线图 plt.plot)
通过 linestyle、color 等参数控制线条外观。
1. color (或 c): 颜色
支持颜色名称(如 ‘red’)、十六进制(‘#FF0000’)、RGB 元组((1,0,0))。
plt.plot(x, y, color='green')
2. linestyle (或 ls): 线型
可选值:‘-’(实线), ‘–’(虚线), ‘-.’(点划线), ‘:’(点线)。
plt.plot(x, y, linestyle='--')
3. linewidth (或 lw): 线宽
plt.plot(x, y, linewidth=3)
4. marker: 数据点标记
可选值:‘o’(圆点), ‘s’(方块), ‘^’(三角形), ‘*’(星号)。
plt.plot(x, y, marker='o')
5. markersize (或 ms): 标记大小
plt.plot(x, y, marker='s', markersize=8)
6. markerfacecolor/markeredgecolor: 标记填充色和边框色
plt.plot(x, y, marker='o', markerfacecolor='red', markeredgecolor='black')
7. alpha: 透明度(0-1)
plt.plot(x, y, alpha=0.5) # 半透明
三、散点图参数(plt.scatter)
专用于 scatter() 的参数:
1. s: 点的大小(标量或数组)
plt.scatter(x, y, s=50) # 统一大小
2. c: 颜色(支持数组映射颜色)
plt.scatter(x, y, c=z, cmap='viridis') # z为数值数组,映射到颜色
3. edgecolors: 点的边框颜色
plt.scatter(x, y, edgecolors='black')
四、坐标轴设置
通过 plt.xlim()、plt.xticks() 等函数调整坐标轴。
1. xlim/ylim: 坐标轴范围
plt.xlim(0, 10)
plt.ylim(-5, 5)
2. xticks/yticks: 刻度位置和标签
plt.xticks([0, 1, 2], ['A', 'B', 'C']) # 设置刻度位置和标签
3. xlabel/ylabel: 坐标轴标签
plt.xlabel('Time (s)', fontsize=12, color='blue')
4. tick_params: 刻度属性
plt.tick_params(axis='x', direction='out', length=8, width=2, colors='red')
五、标题和图例
1. title: 图形标题
plt.title('Temperature Trend', fontsize=14, loc='left') # 左对齐
2. legend: 图例
plt.plot(x, y, label='Line 1')
plt.legend(loc='upper right', fontsize=10, shadow=True)
六、网格和背景
1. grid: 显示网格
plt.grid(True, linestyle='--', alpha=0.6)
2. axis: 坐标轴显示模式
plt.axis('off') # 关闭坐标轴
plt.axis('equal') # 等比例坐标轴
七、保存图形
通过 plt.savefig() 保存为文件。
1. dpi: 保存分辨率
plt.savefig('plot.png', dpi=300)
2. bbox_inches: 去除白边
plt.savefig('plot.png', bbox_inches='tight')
3. transparent: 透明背景
plt.savefig('plot.png', transparent=True)
八、高级参数
rcParams: 全局默认参数设置
plt.rcParams['font.family'] = 'SimHei' # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
子图布局
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[0,0].plot(x, y)
九、子图与单图的语法对比
1. 创建图形
单图:直接使用 plt.figure() 和 plt.plot()。
plt.figure(figsize=(6, 4))
plt.plot(x, y)
子图:通过 plt.subplots() 创建 axes 对象,再对每个子图单独操作。
fig, axes = plt.subplots(2, 2, figsize=(12, 8)) # 2x2 子图
axes[0,0].plot(x, y) # 第一个子图
2. 设置标题和标签
单图:使用 plt.title(), plt.xlabel()。
plt.title("Single Plot")
plt.xlabel("X Axis")
子图:通过 axes 对象调用方法。
axes[0,0].set_title("Subplot 1")
axes[0,0].set_xlabel("X Axis")
3. 调整布局
单图:使用 plt.tight_layout() 自动调整。
plt.tight_layout()
子图:手动调整间距或使用 constrained_layout。
plt.subplots_adjust(wspace=0.3, hspace=0.4) # 调整子图间距
# 或创建时指定:
fig, axes = plt.subplots(2, 2, constrained_layout=True)
十、子图专用功能示例
1. 地图子图
使用 cartopy 在地图子图中添加地理元素:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# 创建带地图投影的子图
fig, ax = plt.subplots(subplot_kw={'projection': ccrs.PlateCarree()})
# 添加地理元素
ax.coastlines(linewidth=0.5)
ax.add_feature(cfeature.BORDERS, linestyle=':')
ax.add_feature(cfeature.LAND, facecolor='lightgray')
ax.gridlines(linestyle='--', alpha=0.5)
# 设置地图范围
ax.set_extent([-180, 180, -60, 90]) # 经度 [-180, 180],纬度 [-60, 90]
2. 多子图共享颜色条
在多个子图之间共享一个颜色条:
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 在两个子图中绘制数据
contour1 = axes[0].contourf(data1, cmap='viridis')
contour2 = axes[1].contourf(data2, cmap='viridis')
# 添加共享颜色条
fig.colorbar(contour1, ax=axes, orientation='horizontal', pad=0.2, label='Value')
3. 子图布局控制
- 自动调整间距
使用 constrained_layout=True 自动优化布局:
fig, axes = plt.subplots(2, 2, constrained_layout=True)
- 手动调整间距
通过 plt.subplots_adjust() 精确控制:
plt.subplots_adjust(
left=0.1, # 左边界
right=0.9, # 右边界
bottom=0.1, # 下边界
top=0.9, # 上边界
wspace=0.3, # 水平间距
hspace=0.4 # 垂直间距
)
4. 完整示例:多子图参数设置
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# 数据生成
x = np.linspace(0, 10, 100)
y = np.sin(x)
data = np.random.rand(10, 10)
# 创建 2x2 子图,包含一个地图子图
fig, axes = plt.subplots(2, 2, figsize=(12, 8), constrained_layout=True)
# --- 第一个子图:折线图 ---
axes[0,0].plot(x, y, color='red', linewidth=2, label='Sin(x)')
axes[0,0].set_title("Line Plot", fontsize=12)
axes[0,0].set_xlabel("X", fontsize=10)
axes[0,0].set_ylabel("Y", fontsize=10)
axes[0,0].legend(loc='upper right')
axes[0,0].grid(True, linestyle='--', alpha=0.5)
# --- 第二个子图:散点图 ---
axes[0,1].scatter(x, y, c=y, cmap='viridis', s=50, edgecolor='black')
axes[0,1].set_title("Scatter Plot", fontsize=12)
axes[0,1].set_xlabel("X", fontsize=10)
# --- 第三个子图:等高线图 ---
contour = axes[1,0].contourf(data, cmap='coolwarm')
axes[1,0].set_title("Contour Plot", fontsize=12)
fig.colorbar(contour, ax=axes[1,0], label='Intensity')
# --- 第四个子图:世界地图 ---
ax_map = axes[1,1]
ax_map = plt.subplot(2, 2, 4, projection=ccrs.PlateCarree()) # 指定地图投影
ax_map.coastlines(linewidth=0.5)
ax_map.add_feature(cfeature.BORDERS, linestyle=':')
ax_map.gridlines(linestyle='--', alpha=0.5)
ax_map.set_title("World Map", fontsize=12)
plt.savefig('subplots_demo.png', dpi=300, bbox_inches='tight')
plt.show()
十一、语法差异总结
功能 | 单图语法 | 子图语法 |
---|---|---|
创建图形 | plt.figure() | fig, axes = plt.subplots(…) |
绘制数据 | plt.plot(x, y) | axes[0,0].plot(x, y) |
设置标题 | plt.title(…) | axes[0,0].set_title(…) |
设置坐标轴标签 | plt.xlabel(…) | axes[0,0].set_xlabel(…) |
设置坐标轴范围 | plt.xlim(…) | axes[0,0].set_xlim(…) |
添加图例 | plt.legend() | axes[0,0].legend() |
添加颜色条 | plt.colorbar() | fig.colorbar(…, ax=axes[x,y]) |
调整布局 | plt.tight_layout() | plt.subplots_adjust(…) |
十二、常见问题
- 如何关闭某个子图的坐标轴?
axes[0,0].axis('off') # 关闭第一个子图的坐标轴
- 如何为不同子图设置不同的投影?
# 创建时指定
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1) # 默认投影
ax2 = fig.add_subplot(1, 2, 2, projection=ccrs.PlateCarree()) # 地图投影
- 如何动态创建子图?
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1) # 2x2 网格中的第一个
ax2 = fig.add_subplot(2, 2, 3) # 第三个位置(左下角)