likes
comments
collection
share

【Python|Matplotlib】Matplotlib库核心内容

作者站长头像
站长
· 阅读数 6

本文参考b站视频进行知识整理,视频指路:Matplotlib核心内容与基本逻辑

文章内容

  • 介绍
  • 快速入门
  • 绘图层次
  • 基本工作流
  • 学习资源

介绍

Matplotlib:Matlab plotting library,是实现 Matlab 画图效果的一个Python包,为很多Python包提供底层工具或画图逻辑。不仅局限于普通的画图,还可以用来绘制动画、交互画图等

快速入门

导包:import matplotlib.pyplot as plt

通过导入pyplot模块,可以使用其中包含的函数来创建图表,该模块提供了一套与Matlab类似的绘图API,因此也被称为Matplotlib的“面向对象接口”.

【Python|Matplotlib】Matplotlib库核心内容
  • 一张坐标系图中各元素的构成

    如果第一次用该库,可以在阅读了解下面的内容后再回看这张图中的元素

利用 plt.plot() 函数分别绘制折线图中的两条线,其中date_lst作为横轴数据,stock_i作为纵轴数据,最后用plt.show()展示绘制的图像,这里是绘制股价随时间的变化折线图。

plt.plot()函数中第一个参数用于指定横轴数据,第二个参数用于每个横轴数据对应的纵轴数据,也就是通过对应位置元素组合得到某条折线中每个点的坐标.

【Python|Matplotlib】Matplotlib库核心内容
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()  # 显示绘制的图像

对图像进行进一步优化:添加标注、图例、标题、线条风格信息

【Python|Matplotlib】Matplotlib库核心内容

plt.plot()函数的第三个参数是一个字符串,用于指定线条的样式和颜色,在字符串中,第一个字符表示线条的颜色,对于示例代码中,'r'代表红色,'b'代表蓝色。第二个字符表示线条的样式,'o'代表圆点,'^'代表三角形。第三个字符表示线条的类型,'-'代表实线,'--'代表虚线。除了使用字符串来指定线条样式和颜色之外,还可以使用关键字参数来指定,例如plt.plot(x, y, color='red', marker='o', linestyle='--')可以实现与'ro--'相同的效果。

ps:matplotlib默认不支持显示中文字体,网上有详细解决方案,可以自行查阅,可以修改原本库中的默认字体,也可以修改全局配置信息或在函数中指定字体,后两种下方会有介绍。

【Python|Matplotlib】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()

对图像进行进一步优化:调整刻度,添加网格

【Python|Matplotlib】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, '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()调整图像的显示范围

【Python|Matplotlib】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, '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()

除了折线图以外的更多基本绘图类型:

【Python|Matplotlib】Matplotlib库核心内容
  • plot(x,y):折线图
  • scatter(x,y):散点图
  • bar(x,height)/barh(y,width):柱状图
  • stem(x,y):火柴图
  • step(x,y):分段折线图
  • fill_between(x,y1,y2):填充图

matplotlib官网提供了各种绘图类型,也包含含有输入输出的示例代码,可以自行参考所需的绘图类型。

Plot types — Matplotlib 3.7.2 documentation

绘图层次

单个图像的构成 (三层分类)

【Python|Matplotlib】Matplotlib库核心内容

matplotlib借鉴了很多matlab的思想,它将一个图像分成三个层次

  1. Axis:指单个数轴
  2. Axes:指坐标系 (例:二维图像由两个数轴(axis)构成)
  3. Figure:指整个画面 (可以包含多个坐标系(axes))
  4. Artist:画面中所有可以看到的东西,都可以称作为一个artist (数轴/图例/边框/线...)

不同层次构成了树状结构

【Python|Matplotlib】Matplotlib库核心内容
  • 整个图包含多个坐标系图,每个坐标系图包含多个数轴
  • 每层都包括上一层的信息和该层的信息
【Python|Matplotlib】Matplotlib库核心内容
  • 一个图可以包含多个坐标系图

绘图逻辑-matlab语法

通过上面介绍的三层分类,也有了我们绘图的基本逻辑:

  1. 创建一个figure (整个图像)
  2. 在指定位置绘制第一个子图 (坐标系图)
  3. 在指定位置绘制第二个子图
  4. ...
【Python|Matplotlib】Matplotlib库核心内容

figure中的子图,可以理解为绘制在figure中的坐标系里

  • 221:绘制2行2列中的第1个图
  • 222:绘制2行2列中的第2个图
  • ...
  • ijk:绘制i行j列中的第k个图

图中所给示例分为两行两列,最多绘制四个图像

顺序:从左到右从上到下

案例

【Python|Matplotlib】Matplotlib库核心内容
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随时间的股价变化

【Python|Matplotlib】Matplotlib库核心内容
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()

绘制三个子图,其中第三个子图纵轴为两股票股价的差值与时间的变化

【Python|Matplotlib】Matplotlib库核心内容
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轴,并设置相关信息

【Python|Matplotlib】Matplotlib库核心内容
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轴是两股票差价

【Python|Matplotlib】Matplotlib库核心内容
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():初始化,返回一个Figure
  • ax=plt.subplot():初始化,并添加一个Axes
  • fig, ax = plt.subplots(m, n):初始化,并添加 mmmnnn 列个Axes
  • ax=fig.add_subplot():添加一个Axes
  • fig.add_gridspec():添加一个网格帮助Axes定位

创建Figure常用参数

① plt.figure(params...)

  • figsize=(6, 6):图像大小 6inch∗6inch6_{inch}*6_{inch}6inch6inch
  • dpi=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,关键词

基本工作流

风格和全局默认设置

  1. 导包,设置风格
  2. 改变全局默认设置
  3. 绘图
    • 一般会给重复使用的图定义特定的绘图函数

① 导包,设置风格

【Python|Matplotlib】Matplotlib库核心内容 【Python|Matplotlib】Matplotlib库核心内容 【Python|Matplotlib】Matplotlib库核心内容

从左到右依次为 '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语法).

【Python|Matplotlib】Matplotlib库核心内容
# 导包
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()

绘图案例

【Python|Matplotlib】Matplotlib库核心内容
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)的交互:

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,设置当前图像

学习资源

转载自:https://juejin.cn/post/7255224807322566714
评论
请登录