【Python|Matplotlib】Matplotlib库核心内容
本文参考b站视频进行知识整理,视频指路:Matplotlib核心内容与基本逻辑
文章内容
- 介绍
- 快速入门
- 绘图层次
- 基本工作流
- 学习资源
介绍
Matplotlib:Matlab plotting library,是实现 Matlab 画图效果的一个Python包,为很多Python包提供底层工具或画图逻辑。不仅局限于普通的画图,还可以用来绘制动画、交互画图等
快速入门
导包:import matplotlib.pyplot as plt
通过导入
pyplot
模块,可以使用其中包含的函数来创建图表,该模块提供了一套与Matlab类似的绘图API,因此也被称为Matplotlib的“面向对象接口”.

- 一张坐标系图中各元素的构成
如果第一次用该库,可以在阅读了解下面的内容后再回看这张图中的元素
利用 plt.plot()
函数分别绘制折线图中的两条线,其中date_lst
作为横轴数据,stock_i
作为纵轴数据,最后用plt.show()
展示绘制的图像,这里是绘制股价随时间的变化折线图。
plt.plot()
函数中第一个参数用于指定横轴数据,第二个参数用于每个横轴数据对应的纵轴数据,也就是通过对应位置元素组合得到某条折线中每个点的坐标.

date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股票1股价
stock_2 = [2, 3, 5, 10, 50] # 股票2股价
plt.plot(date_lst, stock_1) # 绘制股票1的折线图
plt.plot(date_lst, stock_2) # 绘制股票2的折线图
plt.show() # 显示绘制的图像
对图像进行进一步优化:添加标注、图例、标题、线条风格信息

plt.plot()
函数的第三个参数是一个字符串,用于指定线条的样式和颜色,在字符串中,第一个字符表示线条的颜色,对于示例代码中,'r'代表红色,'b'代表蓝色。第二个字符表示线条的样式,'o'代表圆点,'^'代表三角形。第三个字符表示线条的类型,'-'代表实线,'--'代表虚线。除了使用字符串来指定线条样式和颜色之外,还可以使用关键字参数来指定,例如plt.plot(x, y, color='red', marker='o', linestyle='--')
可以实现与'ro--'相同的效果。
ps:matplotlib默认不支持显示中文字体,网上有详细解决方案,可以自行查阅,可以修改原本库中的默认字体,也可以修改全局配置信息或在函数中指定字体,后两种下方会有介绍。

date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股价
stock_2 = [2, 3, 5, 10, 50] # 股价
# plt.plot(date_lst, stock_1, color='red', marker='o', linestyle='--', label='stock-1')
# plt.plot(date_lst, stock_2, color='blue', marker='^', linestyle = '-', labe='stock-2')
plt.plot(date_lst, stock_1, 'ro--', label='stock-1')
plt.plot(date_lst, stock_2, 'b^-',label='stock-2')
plt.title('Line Chart') # 图像标题
plt.xlabel('time') # x轴标注
plt.ylabel('price') # y轴标注
plt.legend() # 添加图例 (查找每个折线的label)
plt.show()
对图像进行进一步优化:调整刻度,添加网格

date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股价
stock_2 = [2, 3, 5, 10, 50] # 股价
plt.plot(date_lst, stock_1, 'ro--', label='stock-1')
plt.plot(date_lst, stock_2, 'b^-',label='stock-2')
plt.title('Line Chart') # 图像标题
plt.xlabel('time') # x轴标注
plt.ylabel('price') # y轴标注
# 设置坐标刻度
plt.xticks([2019,2020,2021,2022,2023])
plt.yticks([10,20,30,40,50])
# 添加辅助线网格
plt.grid()
plt.legend() # 添加图例 (查找每个折线的label)
plt.show()
调整图画的范围:使用plt.xlim()
和plt.ylim()
调整图像的显示范围

date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股价
stock_2 = [2, 3, 5, 10, 50] # 股价
plt.plot(date_lst, stock_1, 'ro--', label='stock-1')
plt.plot(date_lst, stock_2, 'b^-',label='stock-2')
plt.title('Line Chart') # 图像标题
plt.xlabel('time') # x轴标注
plt.ylabel('price') # y轴标注
# 设置坐标刻度
plt.xticks([2019,2020,2021,2022,2023])
plt.yticks([10,20,30,40,50])
plt.grid() # # 添加辅助线网格
# 调整显示范围
plt.xlim(2021.5, 2022.5)
plt.ylim(5, 35)
plt.legend() # 添加图例 (查找每个折线的label)
plt.show()
除了折线图以外的更多基本绘图类型:

plot(x,y)
:折线图scatter(x,y)
:散点图bar(x,height)/barh(y,width)
:柱状图stem(x,y)
:火柴图step(x,y)
:分段折线图fill_between(x,y1,y2)
:填充图
matplotlib官网提供了各种绘图类型,也包含含有输入输出的示例代码,可以自行参考所需的绘图类型。
绘图层次
单个图像的构成 (三层分类)

matplotlib借鉴了很多matlab的思想,它将一个图像分成三个层次
Axis
:指单个数轴Axes
:指坐标系 (例:二维图像由两个数轴(axis)构成)Figure
:指整个画面 (可以包含多个坐标系(axes))Artist
:画面中所有可以看到的东西,都可以称作为一个artist (数轴/图例/边框/线...)
不同层次构成了树状结构

- 整个图包含多个坐标系图,每个坐标系图包含多个数轴
- 每层都包括上一层的信息和该层的信息

- 一个图可以包含多个坐标系图
绘图逻辑-matlab语法
通过上面介绍的三层分类,也有了我们绘图的基本逻辑:
- 创建一个figure (整个图像)
- 在指定位置绘制第一个子图 (坐标系图)
- 在指定位置绘制第二个子图
- ...

figure中的子图,可以理解为绘制在figure中的坐标系里
- 221:绘制2行2列中的第1个图
- 222:绘制2行2列中的第2个图
- ...
- ijk:绘制i行j列中的第k个图
图中所给示例分为两行两列,最多绘制四个图像
顺序:从左到右从上到下
案例

import matplotlib.pyplot as plt
date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股价
stock_2 = [2, 3, 5, 10, 50] # 股价
plt.figure(figsize=(8,4)) # 单位:英寸(inch)
plt.subplot(121) # 1行2列的第1个图
plt.bar(x=date_lst, height=stock_1)
plt.subplot(122) # 1行2列的第2个图
plt.plot(date_lst, stock_2)
plt.show()
设置图像大小用到的figsize参数的单位是英寸(inch),1英寸=2.54厘米
绘图逻辑-OOP(面向对象)语法
上面提到过,图中可见的任何一个元素都能被称为一个Artist,每一个Artist都是一个对象
基本逻辑:
- 指定整体图像中的行和列中包含的子图数和图像大小,得到图像对象和子图坐标系数组
- 对数组中每个坐标系上绘制子图
案例
分别用柱状图和折线图表示股票1和股票2随时间的股价变化

import matplotlib.pyplot as plt
date_lst = [2019,2020,2021,2022,2023] # 时间
stock_1 = [10, 20, 50, 30 ,5] # 股价
stock_2 = [2, 3, 5, 10, 50] # 股价
fig, axes = plt.subplots(1, 2, figsize=(8, 4)) # 返回整体图像(1行2列)和两个坐标系构成的numpy数组
axes[0].bar(date_lst, stock_1) # 图1
axes[1].plot(date_lst, stock_2) # 图2
plt.show()
绘制三个子图,其中第三个子图纵轴为两股票股价的差值与时间的变化

import matplotlib.pyplot as plt
import numpy as np
date_lst = np.array([2019,2020,2021,2022,2023]) # 时间
stock_1 = np.array([10, 20, 50, 30 ,5]) # 股价
stock_2 = np.array([2, 3, 5, 10, 50]) # 股价
fig, axes = plt.subplots(2, 2, figsize=(8, 8)) # 返回整体图像(2行2列)和两个坐标系构成的numpy数组
ax_00 = axes[0, 0]
ax_01 = axes[0, 1]
ax_10 = axes[1, 0]
ax_00.bar(date_lst, stock_1) # 图1
ax_01.plot(date_lst, stock_2) # 图2
ax_10.scatter(date_lst, stock_1-stock_2, # 图3
s=[10, 20, 50, 80, 100], # 大小
c=['r', 'b', 'c', 'k', 'y']) # 颜色
ax_10.set_ylabel('price differences(stock1-stock2)')
plt.show()
丰富每一个图,将整个图像背景设置为灰色,更突出显示每一个子图,统一每个子图的x轴和y轴,并设置相关信息

import matplotlib.pyplot as plt
import numpy as np
date_lst = np.array([2019,2020,2021,2022,2023]) # 时间
stock_1 = np.array([10, 20, 50, 30 ,5]) # 股价
stock_2 = np.array([2, 3, 5, 10, 50]) # 股价
# 背景变为灰色, 所有子图共享x轴和y轴 (sharex/sharey)
fig, axes = plt.subplots(2, 2,
figsize=(8, 8),
facecolor='grey',
sharex=True,
sharey=True,
) # 返回整体图像(2行2列)和两个坐标系构成的numpy数组
ax_00 = axes[0, 0]
ax_01 = axes[0, 1]
ax_10 = axes[1, 0]
axes[1, 1].remove()
ax_00.bar(date_lst, stock_1) # 图1
ax_00.plot(date_lst, stock_1, 'r+-')
ax_01.plot(date_lst, stock_2, 'bo--') # 图2
ax_10.scatter(date_lst, stock_1-stock_2, # 图3
s=[10, 20, 50, 80, 100], # 大小
c=['r', 'b', 'c', 'k', 'y'], # 颜色
)
ax_10.plot(date_lst, stock_1-stock_2, 'k--')
ax_10.set_ylabel('price differences(stock1-stock2)')
# 设置整体图像信息
fig.suptitle('Stock Analysis Chart')
fig.supylabel('price')
fig.supxlabel('years')
plt.show()
绘制添加第四个图并进一步优化图像,第四个图为3D图,x轴为时间信息(年份),y轴为股票1的信息,z轴是两股票差价

import matplotlib.pyplot as plt
import numpy as np
date_lst = np.array([2019,2020,2021,2022,2023]) # 时间
stock_1 = np.array([10, 20, 50, 30 ,5]) # 股价
stock_2 = np.array([2, 3, 5, 10, 50]) # 股价
# 背景变为灰色, 所有子图共享x轴和y轴 (sharex/sharey)
fig, axes = plt.subplots(2, 2,
figsize=(8, 8),
facecolor='grey',
sharex=True,
sharey=True,
) # 返回整体图像(2行2列)和两个坐标系构成的numpy数组
ax_00 = axes[0, 0]
ax_01 = axes[0, 1]
ax_10 = axes[1, 0]
axes[1, 1].remove()
# 图1
ax_00.bar(date_lst, stock_1)
ax_00.plot(date_lst, stock_1, 'r+-')
# 图2
ax_01.plot(date_lst, stock_2, 'bo--')
# 图3
ax_10.scatter(date_lst, stock_1-stock_2,
s=[10, 20, 50, 80, 100], # 大小
c=['r', 'b', 'c', 'k', 'y'], # 颜色
)
ax_10.plot(date_lst, stock_1-stock_2, 'k--')
ax_10.set_ylabel('price differences(stock1-stock2)')
# 由于之前我们remove掉了第四个图, 现在得先添加然后进行相关信息设置
ax_11 = fig.add_subplot(2, 2, 4, projection='3d', facecolor='grey')
ax_11.stem(date_lst, stock_1, stock_1-stock_2,
linefmt='k--',
basefmt='r-', # 基线是一个水平的线条,连接所有垂直线的底部
orientation='z', # 垂直线方向更改为z轴方向
bottom=0, # 基线的高度, 默认为0
)
# 对绘制过的图像进行优化
axes[0, 0].set_facecolor('red')
axes[0, 0].patch.set_alpha(0.1) # 设置face_color的不透明度
ax_11.set_xlabel('years')
ax_11.set_ylabel('price')
ax_11.set_zlabel('differences')
# 设置整体图像信息
fig.suptitle('Stock Analysis Chart')
fig.supylabel('price')
fig.supxlabel('years')
plt.tight_layout() # 保持内容紧凑
plt.show()
其它布局控制方法
上面中介绍的案例使用的是一个基本的布局(plt.subplots()
),如果想使用更加精确、更加不规律的布局,可以使用gridspec
,通过定义网格控制坐标系位置
GridSpec demo — Matplotlib 3.7.1 documentation
对于大部分情况,
plt.subplots()
这种基本方法都可以满足
布局控制和常用参数
Figure布局控制
fig=plt.figure()
:初始化,返回一个Figureax=plt.subplot()
:初始化,并添加一个Axesfig, ax = plt.subplots(m, n)
:初始化,并添加 mmm 行 nnn 列个Axesax=fig.add_subplot()
:添加一个Axesfig.add_gridspec()
:添加一个网格帮助Axes定位
创建Figure常用参数
① plt.figure(params...)
figsize=(6, 6)
:图像大小 6inch∗6inch6_{inch}*6_{inch}6inch∗6inchdpi=300
:每英寸300像素,和图像清晰度有关sharex/sharey=True/False
:Figure中的所有坐标系共享相同的 x/y 显示范围facecolor= 'white'
:Figure背景色为白色edgecolor='white'
:Figure背景边缘为白色
② plt.subplots(params...)
gridspec_kw='height_ratios'
:传入网格参数 (例:[2, 2, 1, 1])subplot_kw='projection'
:用于传递给每个子图的关键字参数。例如,subplot_kw={'projection': '3d'}
表示使用 3D 投影绘制每个子图。('polar':参数,极坐标)
kw:keyword,关键词
基本工作流
风格和全局默认设置
- 导包,设置风格
- 改变全局默认设置
- 绘图
- 一般会给重复使用的图定义特定的绘图函数
① 导包,设置风格



从左到右依次为 'default', 'ggplot', 'seaborn-dark'
import numpy as np
import os
# step 1. 导包
import matplotlib.pyplot as plt
import matplotlib as mpl
# step2. 设置绘图风格
plt.style.use('default') # 默认风格, 其他风格:'ggplot(R语言绘图风格)', 'seaborn-dark'...
plt.plot(np.random.randn(50)) # 默认x轴是 1,2,3,4...,y轴为对应值
# plt.savefig(os.path.join('..','image')) # 保存图像
plt.show()
② 改变全局默认设置
# 自定义常用参数
mpl.rcParams['font.family'] = ['Microsoft YaHei'] # 设置支持中文的字体
mpl.rcParams['figure.dpi'] = 300 # 设置dpi(绘制图像清晰度)
# 查询信息
plt.rcParams.get('figure.figsize') # 默认大小: (6.4 inch, 4.8 inch)
plt.rcParams.get('font.size') # 默认字体大小: 10
# 图画面板调整为白色(默认就是白色)
rc = {'axes.facecolor': 'white', 'savefig.facecolor': 'white'}
mpl.rcParams.update(rc) # 一次更新多个参数
mpl.rcParams['text.usetex'] = True # 打印数学公式
plt.rcParams['figure.constrained_layout.use'] = True # Figure自动调整布局
特殊情况:打印 中文+数学公式;输入数学公式语法和Markdown中公式块的语法一致(latex语法).

# 导包
import matplotlib.pyplot as plt
import matplotlib as mpl
# 设置绘图风格
plt.style.use('ggplot')
# 自定义参数
rc = {
'font.family': 'Microsoft YaHei', # 指定字体
'mathtext.fontset': 'stix', # 数学公式字符集
}
mpl.rcParams.update(rc)
# 在函数使用的时候也可以指定信息
fig, ax = plt.subplots()
# ax.text(0.2, 0.8, r'黑体$\mathrm{Times New Roman}$', fontname='Heiti TC', fontsize=20)
ax.text(0.2, 0.6, r'微软雅黑$Microsoft YaHei$', fontname='Microsoft YaHei', fontsize=30)
plt.xlabel(r'密度$kg/m^3$', fontname='Microsoft YaHei', fontsize=10)
plt.xlim(0.1, 0.9)
plt.ylim(0.5, 0.9)
plt.show()
绘图案例

import matplotlib.pyplot as plt
import numpy as np
def plot_time_series(x, y, fmt, lab='', ax=None):
if ax is None:
ax = plt.subplot()
ax.plot(x, y, fmt, label=lab)
# x轴
ax.set_xlabel('time')
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi/2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi/8))
labs = ax.xaxis.get_ticklabels()
ax.xaxis.set_ticklabels([r'{:.2f}$\pi$'.format(i/2) for i,_ in enumerate(labs)]) # 给每一个刻度设置label
return ax
# 测试数据
x = np.arange(0.01, 10, 0.01)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.log(x)
fig, axes = plt.subplots(2, 1, figsize=(10,6), sharex=True)
plot_time_series(x, y1, 'b-', r'$y=sin(x)$', ax=axes[0])
plot_time_series(x, y2, 'r:', r'$y=cos(x)$', ax=axes[0])
plot_time_series(x, y3, 'g--', ax=axes[1])
# 进一步优化
axes[0].set_xlabel('')
axes[0].legend(loc='upper right')
axes[1].legend(loc='upper right')
axes[0].grid()
axes[1].grid()
# 补充图示
axes[1].lines[0].set_label(r'$y=ln(x)$')
axes[1].legend(loc='upper right')
plt.show()
- ax.xaxis:表示坐标系ax中的x轴(x axis)
- ax.xaxis.set_major_locator(): 设置该坐标系的 x 轴主要刻度定位器
- ax.xaxis.set_minor_locator(): 设置x轴次要刻度定位器
- plt.MultipleLocator(num): 创建一个刻度定位器, 传入的数字就是间隔大小(单位刻度)
后端 / 资源管理
与后端(如 Qt, tkinter)的交互:
- Backends — Matplotlib 3.7.2 documentation
- 交互式画图 (指定后端)
- 静态文件后端:AGG / SVG
- mpl 支持软件开发 ('嵌入' 后端)
Jupyter notebook 中的模式:
%matplotlib inline
:返回静态图像%matplotlib widget
:用于启用交互式的 Matplotlib 图形后端,并支持更高级的交互功能,需安装ipympl
包%matplotlib notebook
:于在交互式的 notebook 环境中启用交互式的 Matplotlib 图形%matplotlib qt
:用于在一个独立的窗口中显示 Matplotlib 图形,并支持交互式操作,需安装qt
一般设定模式后不要反复切换
内存/显示 处理:
plt.show()
:显示当前的 figure 图像plt.close()
:关闭当前的 figure 图像plt.get_fignums()
:查询当前的所有图像编号
删除元素:
plt.clf()
:clear current figure,清理当前图像plt.cla()
:clear current axes,清理当前坐标系plt.close('all')
:close all figure windows,关闭所有图像窗口
get/set 函数
plt.gca()
:get current axes object,获取当前坐标系对象plt.gcf()
:get current figure object,获取当前图像对象plt.sca(ax=ax1)
:set current axes,设置当前坐标系plt.scf(fig=fig)
:set current figure,设置当前图像
学习资源
- matplotlib 官方网站:Examples — Matplotlib 3.7.2 documentation
- Python Graph Gallery:Python Graph Gallery (python-graph-gallery.com)
转载自:https://juejin.cn/post/7255224807322566714