notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • 爬虫

  • Python 数据分析

    • 方法

    • pandas

    • matploitlib

      • 10 分钟上手 matplotlib
        • 1. 简单的画图程序:以折线图为例
          • 1.1 一个最简单的示例
          • 1.2 改线型、给折线加上图例
          • 1.3 调整刻度/添加网格
          • 1.4 添加“长方块”来突出某一部分
          • 1.5 缩放图片,只绘制局部部分
          • 1.6 pyplot.plot() 中的格式 format
          • 1.7 More Plot types
        • 2. 画图层次
          • 2.1 单个图像的构成(三层分类)
          • 2.2 画多个图:使用类似 MATLAB 的语法
          • 2.3 画多个图:基于坐标系对象(Axes)的语法
        • 2.4 更多 Figure 布局
        • 3. 工作基本流程
          • 3.1 导入包,设置风格
          • 3.2 改变全局默认设置
          • 3.3 画图代码复用
        • 4. More
          • 4.1 Jupyter notebook 中的模式
          • 4.2 后端/资源管理
          • 4.3 自学
  • MySQL

  • Redis

  • Elasticsearch

  • Kafka

  • 数据仓库

  • 数据科学
  • Python 数据分析
  • matploitlib
yubin
2022-12-25
目录

10 分钟上手 matplotlib

参考 十分钟讲解Matplotlib的核心内容与基本逻辑 (opens new window)

# 1. 简单的画图程序:以折线图为例

# 1.1 一个最简单的示例

  • 分别用 plt.plot 画出两条折线
import matplotlib.pyplot as plt

# 数据
seasons = [1, 2, 3, 4]
stock1 = [4, 8, 2, 6]
stock2 = [10, 12, 5, 3]

# 画两条折线
plt.plot(seasons, stock1)
plt.plot(seasons, stock2)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
image-20221225155357717

# 1.2 改线型、给折线加上图例

现在对 1.1 示例进行简单的改进:

  • 在 plt.plot 时,增加线型的参数
  • 借助于 xlabel 和 ylabel 方法来增加横纵坐标周的标注
  • 使用 title 方法来添加标题
  • 使用 plt.legend() 添加可视化图例,这需要在 plt.plot 中同时制定每条线的 label
# 改进1: 指定折线图格式
plt.plot(seasons, stock1, "ro--", label="stock code: abc")
plt.plot(seasons, stock2, "b^--", label="stock code: def")
# 线型参数:'[marker][line][color]'

# 改进2: 添加标题,横纵坐标轴标注,图标
plt.title("My Line Chart") # 添加标题
plt.xlabel("quarter") # 标注 x 轴
plt.ylabel("average share price") # 标注 y 轴
plt.legend() # 添加图例(查找每条线的 label)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
image-20221225161219512

# 1.3 调整刻度/添加网格

  • 通过 xticks 和 yticks 设置坐标刻度
  • 通过 plt.grid() 添加辅助线网格
# 在此前的基础上
# 设置 x/y 坐标刻度
plt.xticks([1, 2, 3, 4])
plt.yticks(np.arange(2, 13, 1))
# 添加辅助线网格
plt.grid()
plt.show()
1
2
3
4
5
6
7
image-20221225164743086

# 1.4 添加“长方块”来突出某一部分




 
 
 
 






 
 







# 改进3: 添加一个绿色方块强调两个股票的股价在第4季度反转
import matplotlib.patches as patches

# 创建一个长方体对象
rect = patches.Rectangle((2.5, 1.5), 2, 5, 
                         linewidth=1, edgecolor='g',
                         facecolor='none')
plt.plot(seasons, stock1, "ro--", label="stock code: abc")
plt.plot(seasons, stock2, "b^--", label="stock code: def")
plt.title("My Line Chart")
plt.xlabel("quarter")
plt.ylabel("average share price")

# 添加长方体
plt.gca().add_patch(rect)

plt.legend()
plt.xticks([1, 2, 3, 4])
plt.yticks(np.arange(2, 13, 1))
plt.grid()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
image-20221225165422226

# 1.5 缩放图片,只绘制局部部分

  • 使用 plt.xlim() 和 plt.ylim() 来改变作图范围,只绘制刚刚需要突出的绿方框部分











 
 


# 改进: 改变时间轴的现实范围至上一张图片的绿色框中
plt.plot(seasons, stock1, "ro--", label="stock code: abc")
plt.plot(seasons, stock2, "b^--", label="stock code: def")
plt.title("My Line Chart")
plt.xlabel("quarter")
plt.ylabel("average share price")
plt.legend()

plt.xticks([1, 2, 3, 4])
plt.yticks(np.arange(2, 13, 1))
# 调整显示的范围
plt.xlim(2.5, 4.5)
plt.ylim(1.5, 6.5)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
image-20221225170042742

# 1.6 pyplot.plot() 中的格式 format

下图呈现了多种 format:

image-20221225170428479
  • 格式:点符号 + 颜色 + 连线符号,上图展示了一些经典的组合
    • 在“连线符号”中,一个 - 表示直线,两个组成的 -- 表示虚线
上图的绘图代码
plt.figure(figsize=(9,4))
plt.plot(list(range(5)), [5]*5, 'r.-', label="(r.-)\t\t\t 红色,\t 小圆点,\t 直线")
plt.plot(list(range(5)), [4]*5, 'go--', label="(go--)绿色,\t 大圆点,\t 虚线")
plt.plot(list(range(5)), [3]*5, 'k+-.', label="(k+-.) 黑色,\t 十字点,\t 点虚线")
plt.plot(list(range(5)), [2]*5, 'c*:', label="(c*:)\t\t青色,\t 星号,\t 密集点线")
plt.plot(list(range(5)), [1]*5, 'bs', label="(bs)\t\t 蓝色,\t 方块,\t (不连线)")
plt.annotate("Learn More:\n https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html",
            xy=(0.0, 4.1), fontsize=14)
plt.legend(loc='lower right', prop={'size': 18}) # bbox_to_anchor=(1, -0.1)

plt.show()
1
2
3
4
5
6
7
8
9
10
11

# 1.7 More Plot types

更多可见官网介绍:Plot types (opens new window)

现在我们已经知道了用 pyplot 画图的一些基本方法。

# 2. 画图层次

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

  1. Axis:指单个数轴
  2. Axes:指坐标系(例如:二维图像由两个 Axis 构成)
  3. Figure:指整个画面(可以包含多个坐标系 Axes)
  4. Artist:每个在画面中可以看到的东西(数轴/图示/边框/每条线…)都是一个 Artist,也就是一个画画的元素
image-20221225172014173
  • 上图,从左到右依次是:Axis、Axes、Figure

所有这些 Artist 从小的元素到大的坐标系,都有一个分级体系,不同层次构成了树状结构:

image-20221225172318513

特别看一下 Axes 对比 Figure:

image-20221225172443936
  • 如上图所示,一个 Figure 可以包含多个 axes,这也构成了一个 matplotlib,其实这也是 MATLAB 中图像的一个层次观念。

# 2.2 画多个图:使用类似 MATLAB 的语法

# MATLAB 语法
# 首先用 plt.figure 创建一个 Figure
# figsize=(9, 3) 说明横向长度是 9 英寸(inch),纵向长度为 5 英寸
plt.figure(figsize=(9, 5))

# subplot(211) 表示 2 行 1 列,画第一个图
plt.subplot(211)
plt.bar(seasons, stock1)

# 2 行 1,画第二个图
plt.subplot(212)
plt.plot(seasons, stock2, "b^--")
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 注意 plt.subplot(211) 表示小图的分布式两行一列,现在开始画第一个图

绘制结果:

image-20221225173841575

# 2.3 画多个图:基于坐标系对象(Axes)的语法

# 2.3.1 画两个 Axes

# 面向对象的 OOP 精确语法,现在每一个 Artist 都是一个 py 的对象了
fig, axes = plt.subplots(2, 1,
                         figsize=(6, 6))
axes[0].bar(seasons, stock1)
axes[1].plot(seasons, stock2, "b^--")
plt.show()
1
2
3
4
5
6
  • 使用 plt.subplots 创建了一个 Figure,同时指定参数 2, 1 创建了两行一列的 Axes
  • axes 对象:两个坐标系 Axes 构成的 numpy 数组,相比于之前的方式,代码更加精确

绘图如下:

image-20221225182651329

# 2.3.2 画四个 Axes

给 plt.subplots() 传入参数 2, 2 可以绘制 2 × 2 的 Axes,这个时候对 axes 对象的定位需要使用两个索引,即二维索引来定位。






 











# 数据
seasons = np.array([1, 2, 3, 4])
stock1 = np.array([4, 8, 2, 6])
stock2 = np.array([10, 12, 5, 3])

fig, axes = plt.subplots(2, 2, figsize=(6, 6))
axes[0, 0].bar(seasons, stock1)
axes[0, 1].plot(seasons, stock2, "b^--")
ax = axes[1, 0]
ax.scatter(seasons, stock2 - stock1,
           s=[10, 20, 50, 100],     # size,大小
           c=['r', 'b', 'c', 'y'])  # color,颜色
axes[0, 0].set_title("stock-1")
axes[0, 1].set_title("stock-2")
ax.set_ylabel("price-diff (stock2 - stock1)")
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • axes[0, 1] 就代表第 1 行的第二列的子图

绘制如下:

image-20221225184204113

但在上图中,我们没有用到第四个子图,所以接下来我们把这个 axes 删掉。

# 2.3.3 删掉某个 axes

  • 可以通过 axes[1, 1].remove() 删除掉第四个坐标系
  • 对 fig 调用相关方法可以修改 Figure 级别的相关信息






 












 
 
 
 



# Figure 控制 x/y 轴数值相等,背景为灰色
fig, axes = plt.subplots(2, 2, figsize=(6, 6),
                         facecolor="grey",  # 修改背景颜色
                         sharex=True, sharey=True)

# 删除最后一个坐标系
axes[1, 1].remove()

# 中间的这些代码不变
axes[0, 0].bar(seasons, stock1)
axes[0, 1].plot(seasons, stock2, "b^--")
ax = axes[1, 0]
ax.scatter(seasons, stock2 - stock1,
           s=[10, 20, 50, 100],
           c=['r', 'b', 'c', 'y'])
axes[0, 0].set_title("stock-1")
axes[0, 1].set_title("stock-2")
ax.set_ylabel("price-diff (stock2 - stock1)")

# Figure 对象添加整体大标题/注释
fig.suptitle("Stcok Analysis Chart")
fig.supylabel("stock price")
fig.supxlabel("seasons")

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
image-20221225185328854

# 2.3.4 添加第四个 3D 图

其实所谓的 3D 图就是三个坐标轴组成的坐标系,x 轴是之前的时间信息,y 轴是 stock 1 的信息,z 轴是两个 stock 的差价,代码如下:

























 
 
 
 
 
 
 
 
 
 



fig, axes = plt.subplots(2, 2, figsize=(8, 8),
                         facecolor="grey",  # 修改背景颜色
                         sharex=True, sharey=True)
# 绘制上面的两个坐标系
axes[0, 0].bar(seasons, stock1)
axes[0, 1].plot(seasons, stock2, "b^--")
axes[0, 0].set_title("stock-1")
axes[0, 1].set_title("stock-2")

# 绘制 axes[1, 0]
ax = axes[1, 0]
ax.scatter(seasons, stock2 - stock1,
           s=[10, 20, 50, 100],
           c=['r', 'b', 'c', 'y'])
ax.plot(seasons, stock2 - stock1, "--", color="black")
ax.set_ylabel("price-diff (stock2 - stock1)")

# 设置 figure 级别的信息
fig.suptitle("Stcok Analysis Chart")
fig.supylabel("stock price")
fig.supxlabel("seasons")

# 删除右下角的坐标系
axes[1, 1].remove()
# 重新添加右下角坐标系(改变为三维坐标系)
ax = fig.add_subplot(2, 2, 4,
                     projection='3d', facecolor='grey')
ax.stem(seasons, stock1, stock2 - stock1)  # 使用 stem 创建茎图
ax.stem(seasons, stock1, stock2 - stock1,
        linefmt='k--', basefmt='k--',
        bottom=10, orientation='y')
ax.set_xlabel('season (x)')
ax.set_ylabel('stock-1 (y)')
ax.set_zlabel('price-diff (z)')

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
image-20221225200205996

在绘制出图片后,我们要时时对它进行优化,比如这里可以将第一个子图和最后一个 3D 图呼应一下:






 
 
 


























 
 
 
 








fig, axes = plt.subplots(2, 2, figsize=(8, 8),
                         facecolor="grey",
                         sharex=True, sharey=True)
# 绘制上面的两个坐标系
axes[0, 0].bar(seasons, stock1)
axes[0, 0].plot(seasons, stock1, 'r+-')  # 在柱状图上在绘制一个折线图
axes[0, 0].set_facecolor('red')     # 背景设为红色
axes[0, 0].patch.set_alpha(0.2)     # 背景颜色透明度
axes[0, 1].plot(seasons, stock2, "b^--")
axes[0, 0].set_title("stock-1")
axes[0, 1].set_title("stock-2")

# 绘制 axes[1, 0]
ax = axes[1, 0]
ax.scatter(seasons, stock2 - stock1,
           s=[10, 20, 50, 100],
           c=['r', 'b', 'c', 'y'])
ax.plot(seasons, stock2 - stock1, "--", color="black")
ax.set_ylabel("price-diff (stock2 - stock1)")

# 设置 figure 级别的信息
fig.suptitle("Stcok Analysis Chart")
fig.supylabel("stock price")
fig.supxlabel("seasons")

# 删除右下角的坐标系
axes[1, 1].remove()
# 重新添加右下角坐标系(改变为三维坐标系)
ax = fig.add_subplot(2, 2, 4,
                     projection='3d', facecolor='grey')
ax.stem(seasons, stock1, stock2 - stock1)
ax.stem(seasons, stock1, stock2 - stock1,
        linefmt='k--', basefmt='k--',
        bottom=10, orientation='y')
ax.plot_surface(np.array([1,1,4,4]).reshape(2,2),
                np.array([2.5,10,2.5,10]).reshape(2,2),
                np.array([0]*4).reshape(2,2), 
                alpha=0.2, color='red')
ax.set_xlabel('season (x)')
ax.set_ylabel('stock-1 (y)')
ax.set_zlabel('price-diff (z)')

# 保持“内容紧凑”
plt.tight_layout()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
image-20221225201226441

这里用到的 ax.plot_surface 的具体用法可以先不用关系,看懂其他的就可以了。

# 2.4 更多 Figure 布局

刚刚使用的 plt.subplots 只是一个基本的布局,如果需要使用一个更加精确、更加不规律的布局的话,可以使用 gridspec 来进行布局,gridspec 通过定义网格控制坐标系位置,通常采用如下四个语法来进行画图:

  • fig = plt.figure():初始化,返回一个 Figure 画面,还需要继续去添加坐标系
  • ax = plt.subplot():初始化,并且添加一个 Axes 并返回了它
  • fig, ax = plt.subplots(m, n):初始化,并且添加 m 行 n 列个 Axes
  • ax = fig.add_subplot():添加一个 Axes

plt.figure 常用参数

plt.figure(参数…)

  • figsize=(6, 6):6 英寸 × 6 英寸的图像
  • dpi=300:每英寸 300 个点像素,默认是 100,现在常改为 300
  • sharex / sharey = True/False:坐标系共享相同的 x/y 显示范围
  • facecolor=‘white’:Figure 背景设置为白色,否则为透明
  • edgecolor=‘white’:Figure 背景边缘设置为白色,否则为透明

plt.subplots 常用参数

plt.subplots(参数…)

  • gridspec_kw=‘height_ratios’: [2, 2, 1, 1] 传入网格参数
  • subplot_kw=‘projection’: ‘polor’ 传入 add_subplot 函数中的参数,这里改变为极坐标

# 3. 工作基本流程

这里主要讲一下你的工作基本流程。

# 3.1 导入包,设置风格

# 3.1.1 style: default

#### step 1. 导入包 ####
import matplotlib.pyplot as plt
import matplotlib as mpl

#### step 2. 设置画图风格 ####
plt.style.use('default')
plt.plot(np.random.randn(50))
plt.show()
1
2
3
4
5
6
7
8
image-20221225203325833

# 3.1.2 style: R 画图风格

plt.style.use('ggplot')
plt.plot(np.random.randn(50))
plt.show()
1
2
3
image-20221225203449717

# 3.1.3 style: seaborn-dark

plt.style.use('seaborn-dark')
plt.plot(np.random.randn(50))
plt.show()
1
2
3
image-20221225203623116

# 3.2 改变全局默认设置

这里需要设置一些常用的全局配置参数。

# 设置支持中文字体(黑体)
mpl.rcParams['font.family'] = ['Heiti SC']
# 设置 dpi,提高图片清晰度
# 这样设置后就不需要以后每次生产 Figure 都去重新设置
mpl.rcParams['figure.dpi'] = 300

# 默认大小尺寸 [6.4 inch, 4.8 inch]
# 1 inch = 2.54 cm
plt.rcParams.get('figure.figsize')
# 默认字体大小:10.0
# 这个字体大小其实与 Word 中的字体大小是一个意思
plt.rcParams.get('font.size')

# 图画面板调整为白色
rc = {
    'axes.facecolor': 'white',
    'savefig.facecolor': 'white'
}
mpl.rcParams.update(rc) # 一次更新多个值
# 打印数学公式
mpl.rcParams['text.usetex'] = True
# Figure 自动调整格式
plt.rcParams['figure.constrained_layout.use'] = True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
查询当前你的计算机中matplotlib的可用字体
# 例子:查询当前你的计算机中matplotlib的可用字体
import matplotlib.font_manager as fm

fm._load_fontmanager(try_read_cache=False)
fpaths = fm.findSystemFonts(fontpaths=None)
# print(fpaths)
exempt_lst = ["NISC18030.ttf", "Emoji"]
skip=False
for i in fpaths:
    # print(i)
    for ft in exempt_lst:
        if ft in i:
            skip=True
    if skip==True:
        skip=False
        continue
    f = matplotlib.font_manager.get_font(i)
    print(f.family_name)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.3 画图代码复用

我们往往会写一个画图函数来方便之后复用,一个示例如下:









 






















# 三个“三角函数”
x = np.linspace(0, 10, 100)
y1 = np.cos(x)
y2 = np.sin(x)
y3 = np.tanh(x) # tanh函数

# 画时间序列曲线
# 输入/输出都包含坐标轴变量
def plot_time_series(x, y, fmt, lab="", ax=None):
    if ax is None:
        fig, 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 / 4))
    labs = ax.xaxis.get_ticklabels()
    ax.xaxis.set_ticklabels([r"{:.2f}$\pi$".format(i/2) for i, l in enumerate(labs)])
    return ax

# 两个坐标周
fig, axes = plt.subplots(2, 1, figsize=(6, 3),
                         sharex=True, facecolor="white")
# 在第一个坐标周画两条线
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])

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  • 这个需要复用的函数往往设计成:需要传入 ax,然后函数再返回 ax,而具体的 ax 实例对象是在外部生成的,这个函数只专心于对给定的 ax 绘图。
image-20221225205407251

# 4. More

# 4.1 Jupyter notebook 中的模式

  • %matplotlib inline:返回静态图像
  • %matplotlib widget:安装 ipympl 包 <- JupyterLab
  • %matplotlib notebook <- Jupyter Notebook
  • %matplotlib qt:如果安装了 qt

一般设定模式后不要反复切换。

# 4.2 后端/资源管理

# 内存/显示处理
plt.show()  # 显示当前 figure 对象
plt.close() # 关闭当前 figure 对象
plt.get_fignums()   # 查询当前的所有图像编号
1
2
3
4
# 删除元素(用于尽快清理内存)
plt.clf()   # clear current figure
plt.cla()   # clear current axes
plt.close('all')    # close all figure windows
1
2
3
4

# 4.3 自学

  • https://matplotlib.org/stable/gallery/index.html (opens new window)
    • 根据类型搜索
    • 根据语法搜索
  • https://www.python-graph-gallery.com/ (opens new window)
    • 更全面图片分类
    • 收集了网络中很多精美的画图 + 源代码
  • https://r-graph-gallery.com/ (opens new window)
  • https://d3-graph-gallery.com/ (opens new window)
  • 非编程(非自动化)画图:如:PPT;Adobe Illustrator;
编辑 (opens new window)
上次更新: 2022/12/25, 15:53:12
10 分钟上手 pandas
基础架构:一条SQL查询语句是如何执行的?

← 10 分钟上手 pandas 基础架构:一条SQL查询语句是如何执行的?→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×