47.Python编程:matplotlib详解

作者: TensorFlow开发者 | 来源:发表于2018-10-10 01:16 被阅读271次

    前言

    有时候为了直观,我们需要将数据可视化,Python编程中最为常用的一个库是matplotlib。那么什么是matplotlib

    Matplotlib 官方是这样定位自己的:

    Matplotlib is a Python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms.

    Matplotlib tries to make easy things easy and hard things possible. You can generate plots, histograms, power spectra, bar charts, errorcharts, scatterplots, etc., with just a few lines of code.

    Matplotlib是一个Python 2D绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形。

    Matplotlib试图让简单的事情变得更简单,让无法实现的事情变得可能实现。 只需几行代码即可生成绘图,直方图,功率谱,条形图,错误图,散点图等。

    总之一句话:Matplotlib让绘图变成了一件非常简单的事情。

    安装及导入matplotlib

    安装matplotlib的指令:

    pip install matplotlib
    

    需要注意的是,matplotlib需要numpy的支持,如果你还没安装numpy,请先安装numpy:

    pip install numpy
    

    推荐的导入matplotlib写法:

    import matplotlib.pyplot as plt
    

    如果你还没用过numpy,可以先去了解一下numpy基础知识后,再回过头学习此节知识点。

    核心概念

    • figure

    matplotlib官方文档中找到关于figure的定义和解释:
    1.the Figure, which contains all the plot elements.
    2.The top level container for all the plot elements.
    figure是一顶级的容器,包含了绘图所有的元素。

    如果觉得不好理解,我们可以简单粗暴地理解为,每一个绘图弹框就是一个figure,绘图弹框样式,如下图:

    figure

    figure中的一切元素都可以根据业务需求或个人喜好自定义:弹框的标题、坐标轴位置、坐标轴精度、坐标轴刻度、坐标轴显示或隐藏、绘图的线条样式、线条宽度、线条颜色、图例、注解等所有元素。

    元素示意图

    【说明】
    1.如果需要图像在多个不同的figure弹框中展示,则需要获取多个figure才可以,获取figure的方式是:fig = plt.figure()

    2.一个figure到下一个figure语句前之间的区域,属于该figure的作图管辖范围;而如果没有下一个figure时,则到plt.show()之间的区域,属于该figure的作图管辖范围。在一个figure的作图管辖范围的图像都会展示在同一个figure绘画弹框中。

    3.获取figure:

    fig = plt.figure()
    

    或者获取figure的同时指定figure绘画框序号、尺寸大小:

    fig = plt.figure(num=22, figsize=(200, 200))
    
    • 图像显示必须show()

    matplotlib作图,要显示图像,必须调用plt.show(), 否则不显示。

    多个图像绘制在单一figure,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig1 = plt.figure(num=11)
    # x
    x = np.linspace(-5, 5, 20)
    
    # y1
    y = x * 2 + 1
    
    # 绘图y
    plt.plot(x, y)
    
    # y2
    y2 = x ** 2
    plt.plot(x, y2)
    
    # 显示图像
    plt.show()
    

    运行结果:


    多个图像绘制在单一figure中

    多个图像分别绘制在各自figure中,完整示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # figure
    fig1 = plt.figure(num=11)
    # x
    x = np.linspace(-5, 5, 20)
    
    # y1
    y = x * 2 + 1
    
    # 绘图y
    plt.plot(x, y)
    
    # figure
    fig12 = plt.figure(num=12)
    
    # y2
    y2 = x ** 2
    plt.plot(x, y2)
    
    # 显示图像
    plt.show()
    

    上面代码在y1绘制后,新起了一个figure,对应上面倒数第4行有效代码:fig12 = plt.figure(num=12)。此时再运行,会有两个图像弹框,运行结果如下:

    对应代码fig1 = plt.figure(num=11) 对应代码fig12 = plt.figure(num=12)

    坐标轴设置

    坐标轴未进行任何设置时,会采用默认设置和自适应,如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # x
    x = np.random.randn(10)
    
    # y
    y = x * 2 + 1
    
    # 绘图
    plt.plot(x, y)
    
    # 显示图像
    plt.show()
    

    运行结果:


    坐标轴未设置时自适应

    如果我们觉得上面不符合我们的业务需求或个人喜好,则可以自定义。比如我们可以:

    • 坐标轴描述
    • 坐标轴范围设置
    • 坐标轴刻度
    • 挪动坐标轴

    坐标轴描述

    添加坐标轴描述,设置x轴plt.xlabel("x轴自定义描述"),设置y轴plt.ylabel("用轴自定义描述")。完整示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # x
    x = np.random.randn(10)
    
    # y
    y = x * 2 + 1
    
    # 绘图
    plt.plot(x, y)
    
    # 设置x轴
    plt.xlabel("This is X axis")
    
    # 设置y轴
    plt.ylabel("This is Y axis")
    
    # 显示图像
    plt.show()
    

    运行结果:


    坐标轴描述
    设置坐标轴范围

    设置坐标轴范围,设置x轴范围plt.xlim(tuple),形如plt.xlim((-5, 5));设置y轴plt.ylim(tuple),形如plt.ylim((-5, 5))。完整示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # x
    x = np.random.randn(10)
    
    # y
    y = x * 2 + 1
    
    # 绘图
    plt.plot(x, y)
    
    # 设置x轴
    plt.xlabel("X")
    
    # 设置y轴
    plt.ylabel("Y")
    
    # 设置x轴范围
    plt.xlim((-5, 5))
    
    # 设置y轴范围
    plt.ylim((-5, 10))
    
    # 显示图像
    plt.show()
    

    运行结果:


    设置坐标轴范围
    坐标轴刻度

    设置坐标轴范围,设置x轴范围plt.xticks(arr);设置y轴plt.yticks(arr)

    【提示】ticks有记号的含义。

    将上面例子,加以坐标轴刻度显示设置,示例如下:

    # 设置x轴刻度显示
    plt.xticks([-2.0, -1.0, 0, 1, 2, 4, 8])
    
    # 设置y轴刻度显示
    plt.yticks(np.linspace(-3, 3, 10))
    

    运行结果:


    坐标轴刻度

    特别地,如果想要隐藏坐标轴刻度,则可以这样设置,入参传入空的元组(), 形如:plt.xticks(())plt.yticks(()),分别表示隐藏x轴刻度显示和隐藏y轴刻度。

    # 隐藏x轴刻度显示
    plt.xticks(())
    
    # 隐藏y轴刻度
    plt.yticks(())
    

    运行结果:


    隐藏坐标轴刻度
    挪动坐标轴

    在上面介绍图像弹框元素时,给出了一个图片。其中,图像四周各有一条黑色实线,叫做spines,坐标轴就是其中的右侧和底部的两条。要挪动坐标轴,说白了就是挪动右侧和底部的这两条spine

    元素示意图

    知道了以上信息,如果想要把坐标轴从两边挪到坐标轴0刻度位置,我们可以这么干:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 移动坐标轴
    
    figure = plt.figure(num=100)
    
    # x,y
    x = np.linspace(-4, 4, 50)
    y = x ** 2 - 4
    
    # 获取到坐标轴
    ax = plt.gca()
    
    # 隐藏右边、上边的spine
    ax.spines["right"].set_color("none")
    ax.spines["top"].set_color("none")
    
    # 移动两个spine到0,0,达到把坐标轴移动的目的
    ax.spines["bottom"].set_position(("data", 0))
    ax.spines["left"].set_position(("data", 0))
    
    xx_label = r"y = x ^ 2 - 4"
    x_label = r"y = x"
    plt.title("here is title")
    
    # 绘图
    plt.plot(x, y, color="#ff0000")
    
    # 显示图例
    plt.legend()
    
    plt.plot(x, x)
    
    # 显示网格
    plt.grid(True)
    
    # 显示图例
    plt.legend(labels=[xx_label, x_label])
    
    plt.show()
    

    运行结果:


    显示网格

    一个figure中,默认是隐藏网格的。要显示网格,只需要设置:plt.grid(True)即可。上面挪动坐标轴的例子中,已有该项设置,可参考倒数第3行设置。

    散点图scatter

    matplotlib中绘制散点图,只需要将之前绘制图像的plt.plot(),改用plt.scatter(x_arr, y_arr)即可。当然可以在绘制的时候,进行一些个性化设置,形如:
    plt.scatter(x_arr, y_arr, s=25, alpha=0.75, cmap="bone")
    x_arr表示横坐标数据组成的数组;
    y_arr表示纵坐标数据组成的数组;
    s=25表示点的大小;
    alpha=0.75表示点的不透明度;
    cmap="bone"表示颜色映射,其中cmap中的ccolor的首字母。

    绘制散点图,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 散点图
    # x, y
    x = np.random.normal(0, 1, 20)
    y = np.random.normal(0, 1, 20)
    
    # 绘制散点图
    plt.scatter(x, y, s=25, alpha=0.75)
    
    # 隐藏坐标轴刻度
    plt.xticks(())
    plt.yticks(())
    
    # 显示图像
    plt.show()
    

    运行结果:


    散点图

    直方图

    要绘制直方图,只需要将之前绘制图像的plt.plot(),改用plt.bar(x_arr, y_arr)即可。当然可以在绘制的时候,进行一些个性化设置,形如:plt.bar(x_arr, y_arr, facecolor="#999999", edgecolor="white")
    x_arr表示直方图x数据组成的数组;
    y_arr表示直方图y数据组成的数组;
    facecolor="#999999"表示直方图的颜色;
    edgecolor="white"表示直方图的边框颜色;

    绘制直方图,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    # 直方图
    
    # x, y
    size = 12
    x = np.arange(size)
    y = np.random.uniform(0, 1, size) * 10
    
    # 直方图
    plt.bar(x, y, edgecolor="white")
    plt.bar(x, -y, facecolor="#999999", edgecolor="white")
    
    # 设置坐标
    plt.xticks(x)
    plt.yticks(np.linspace(-12, 12, 13))
    
    # 显示数值
    for (X, Y) in zip(x, y):
        plt.text(x=X, y=Y+0.2, s="%.1f" % Y, ha="center")
        print(X, Y)
    
    # 显示图像
    plt.show()
    

    运行结果:


    直方图

    等高线

    要绘制等高线,只需要将之前绘制图像的plt.plot(),改用plt.contour(X, Y, f(X, Y), 10)即可。当然可以在绘制的时候,进行一些个性化设置,例如,设置等高线之间颜色填充:plt.contourf(X, Y, f(X, Y), 10, alpha=0.75, cmap=plt.cm.hot),核心代码如下:

    # 关联表格
    X, Y = np.meshgrid(x, y)
    
    # 绘制等高线
    c = plt.contour(X, Y, f(X, Y), 10, color="black", linewidth=0.5)
    
    # 设置等高线之间颜色填充
    plt.contourf(X, Y, f(X, Y), 10, alpha=0.75, cmap=plt.cm.hot)
    
    # 显示高度
    plt.clabel(c, inline=True)
    

    说明:绘制等高线c = plt.contour(X, Y, f(X, Y), 10, color="black", linewidth=0.5)参数说明:
    X表示直方图x数据组成的数组;
    Y表示直方图y数据组成的数组;
    f(X, Y)表示根据X、Y计算高度的一个函数;
    color="black"表示等高线的颜色;
    linewidth=0.5表示等高线的线条宽度;

    示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    # 等高线
    
    n = 64
    
    x = np.linspace(-3, 3, n)
    y = np.linspace(-3, 3, n)
    
    
    # 定义等高线高度函数
    def f(x, y):
        return (1 - y / 2 + x ** 5 + y ** 5) * np.exp(- x ** 2 - y ** 2) * 100
    
    
    # 生成网格采样点
    X, Y = np.meshgrid(x, y)
    
    # 绘制等高线
    c = plt.contour(X, Y, f(X, Y), 10, color="black", linewidth=0.5)
    
    # 设置等高线之间颜色填充
    plt.contourf(X, Y, f(X, Y), 10, alpha=0.75, cmap=plt.cm.hot)
    
    # 显示高度
    plt.clabel(c, inline=True)
    
    plt.xticks(())
    plt.yticks(())
    plt.show()
    

    运行结果:


    等高线

    图片

    为了能有图片的数据,我们先读取一个图片data = plt.imread("yellow.png")。为了能根据图片数据绘制图片,只需要plt.imshow(data),参数是上面拿到的图片的数据。这样就可以绘制图片了,示例如下:

    import matplotlib.pyplot as plt
    
    # 图片
    
    # 拿到图片资源
    data = plt.imread("yellow.png")
    print(data)
    
    # 绘制图片
    plt.imshow(data)
    plt.show()
    

    运行结果:

    [[[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]
    
     [[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]
    
     [[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]
    
     ...
    
     [[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]
    
     [[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]
    
     [[1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      ...
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]
      [1. 1. 1. 1.]]]
    
    显示图片

    3D图像

    我们已经知道,默认情况下画出的是2D图像,如果想要画3D图像,我们需要导入matplotlib中的3D模块:from mpl_toolkits.mplot3d import Axes3D
    我们需要先将figure变成3D,这是绘制3D图像的基础:

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    
    # 3D 图像
    figure = plt.figure()
    
    # 将figure变为3d
    ax = Axes3D(figure)
    

    运行结果:


    将figure变为3D

    有了3Dfigure,我们就可以在此基础上绘制3D图像了:ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')其中:
    X表示3维中的x;
    Y表示3维中的y;
    Z表示3维中的z;
    rstride=1cstride=1分别表示x、y方向3D图像跨度,值越小越细致,越大越粗略;
    cmap='rainbow'表示颜色映射;

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    
    
    # 3D 图像
    figure = plt.figure()
    
    # 将figure变为3d
    ax = Axes3D(figure)
    
    # 定义x, y
    x = np.linspace(-2 * np.pi,  2 * np.pi, 50)
    y = np.linspace(-2 * np.pi, 2 * np.pi, 50)
    
    # 生成网格采样点
    X, Y = np.meshgrid(x, y)
    
    r = np.sqrt(X ** 2 + Y ** 2)
    
    Z = - np.cos(r)
    
    # 绘制3D图像
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')
    
    # 绘制从3D曲面到底部的投影
    ax.contour(X, Y, Z, zdim='z', offset=-4, cmap='rainbow')
    ax.contourf(X, Y, Z, zdim='z', offset=-4, cmap='rainbow')
    
    # 设置z轴范围
    ax.set_zlim((-2, 2))
    plt.show()
    

    运行结果:


    3D图像

    说明:
    1.为了方便查看3D图像,我们可以拖拽旋转。


    拖拽旋转查看3D图像

    2.让3D图像更加直观,我们又在底部添加了登高线图。当然这一部分可以不添加。

    # 绘制从3D曲面到底部的投影
    ax.contour(X, Y, Z, zdim='z', offset=-4, cmap='rainbow')
    ax.contourf(X, Y, Z, zdim='z', offset=-4, cmap='rainbow')
    

    多子图绘制

    要想实现多子图绘制,matplotlib中提供了4种方式:plt.subplot()、pltsubplot2gird()、plt.subplots()、gridspec

    plt.subplot()方式

    plt.subplot()方式绘制多子图,只需要传入简单几个参数即可:plt.subplot(rows, columns, current_subplot_index),形如plt.subplot(2, 2, 1),其中:
    rows表示最终子图的行数;
    columns表示最终子图的列数;
    current_subplot_index表示当前子图的索引;

    当然,这几个参数是可以连写在一起的,同样可以被识别。例如:上面的plt.subplot(2, 2, 1),我们同样可以这样写plt.subplot(221),两者是等价的。

    plt.subplot()方式绘制多子图,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 子图1
    plt.subplot(2, 2, 1)
    plt.scatter(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图2
    plt.subplot(2, 2, 2)
    plt.plot(np.linspace(-2, 2, 5), np.random.randn(5))
    plt.grid(True)
    
    # 子图3
    plt.subplot(2, 2, 3)
    x = np.linspace(0, 5, 5)
    plt.bar(x, np.random.random(5))
    plt.xticks(np.arange(0, 6))
    
    # 子图4
    plt.subplot(2, 2, 4)
    plt.pie(np.random.random(5), labels=list("ABCDE"))
    
    plt.show()
    

    运行结果:


    plt.subplot方式绘制多子图
    pltsubplot2gird()方式

    plt.pltsubplot2gird()方式绘制多子图,只需要传入简单几个参数即可:plt.pltsubplot2gird(shape, loc, rowspan=, colspan=),形如plt.subplot((2, 2), (0, 1), rowspan=2, colspan=2),其中:
    shape表示由最终子图的行数、列数组成的元组,如(2, 2);
    loc表示当前子图所在的行数和列数组成的元组,如(0, 1);
    rowspan=表示当前子图的所跨的行数,默认值为1;
    colspan=表示当前子图的所跨的列数,默认值为1;

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 方式2:plt.subplot2grid()
    
    # 子图1
    shape = (3, 3)
    plt.subplot2grid(shape=shape, loc=(0, 0))
    plt.scatter(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图2
    plt.subplot2grid(shape=shape, loc=(0, 1), colspan=2)
    plt.plot(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图3
    plt.subplot2grid(shape=shape, loc=(1, 0))
    x = np.linspace(0, 5, 5)
    plt.bar(x, np.random.random(5))
    plt.xticks(np.arange(0, 6))
    plt.ylim((0, 1.5))
    
    # 子图4
    plt.subplot2grid(shape=shape, loc=(1, 1), rowspan=2)
    plt.scatter(np.linspace(-2, 2, 10), np.random.randn(10))
    
    # 子图5
    plt.subplot2grid(shape=shape, loc=(1, 2))
    plt.pie(np.random.random(5), labels=list("ABCDE"))
    
    # 子图6
    plt.subplot2grid(shape=shape, loc=(2, 0))
    plt.pie(np.random.random(5), labels=["Chinese", "English", "math", "chem", "biology"])
    
    # 子图7
    plt.subplot2grid(shape=shape, loc=(2, 2))
    x = np.linspace(0, 5, 5)
    plt.bar(x, np.random.random(5))
    plt.xticks(np.arange(0, 6))
    plt.ylim((0, 1.5))
    
    plt.show()
    
    pltsubplot2gird()方式绘制多子图

    上面多子图,一一对应的索引如下:

    多子图对应索引
    plt.subplots()方式

    plt.subplots()方式绘制多子图,只需要传入简单几个参数即可:fig, ((ax00, ax01), (ax10, ax11)) = plt.subplots(rows, cols, sharex=True, sharey=True),其中:
    rows表示最终子图的行数;
    cols表示最终子图的行数;
    sharex=True表示是否共享x轴,默认值为False;
    sharey=True表示是否共享y轴,默认值为False;

    形如fig, ((ax00, ax01), (ax10, ax11)) = plt.subplots(2, 2, sharex=False, sharey=False)

    提示:返回值中,fig表示figure,如果上面入参2行2列,则返回还有:((ax00, ax01), (ax10, ax11)),其中,ax00表示第(0, 0)ax01表示第(0, 1)ax10表示第(1, 0)ax11表示第(1, 1)位置处的子图;我们就可以拿着这些去画子图:

    # 方式3 plt.subplots()
    fig, ((ax00, ax01), (ax10, ax11)) = plt.subplots(2, 2, sharex=False, sharey=False)
    
    # 子图1
    ax00.scatter(np.linspace(-2, 2, 5), np.random.randn(5))
    

    使用plt.subplots()的方式绘制多子图,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 方式3 plt.subplots()
    fig, ((ax00, ax01), (ax10, ax11)) = plt.subplots(2, 2, sharex=False, sharey=False)
    
    # 子图1
    ax00.scatter(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图2
    ax01.plot(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图3
    x = np.linspace(0, 5, 5)
    ax10.bar(x, np.random.random(5))
    
    # 子图4
    ax11.pie(np.random.random(5), labels=list("ABCDE"))
    
    plt.show()
    

    运行结果:


    plt.subplots()方式绘制多子图
    gridspec方式

    gridspec方式绘制多子图,需要额外导入一个模块:

    import matplotlib.gridspec as gridspec
    

    此时,只需要传入简单几个参数即可:my_gridspec = gridspec.GridSpec(rows, cols),其中:
    rows表示最终子图的行数;
    cols表示最终子图的行数;

    要想绘制子图,我们先通过ax00 = plt.subplot(my_gridspec[0, 0])拿到子图,my_gridspec[0, 0]表示第0行第0列处的子图,即:第(0, 0)位置的子图,依次类推。

    # 子图1
    ax00 = plt.subplot(my_gridspec[0, 0])
    

    gridspec方式绘制多子图,示例如下:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.gridspec as gridspec
    
    # 方式4
    my_gridspec = gridspec.GridSpec(2, 2)
    
    # 子图1
    ax00 = plt.subplot(my_gridspec[0, 0])
    ax00.scatter(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图2
    ax01 = plt.subplot(my_gridspec[0, 1])
    ax01.plot(np.linspace(-2, 2, 5), np.random.randn(5))
    
    # 子图3
    ax10 = plt.subplot(my_gridspec[1, 0])
    ax10.pie(np.random.random(5), labels=list("ABCDE"))
    
    # 子图4
    ax11 = plt.subplot(my_gridspec[1, 1])
    x = np.linspace(0, 5, 5)
    ax11.bar(x, np.random.random(5))
    
    plt.show()
    

    运行结果:


    gridspec方式绘制多子图

    动态图像

    制作动态图像,matplotlib官方是这么介绍的:
    The easiest way to make a live animation in matplotlib is to use one of the Animation classes.

    方式 特点
    FuncAnimation Makes an animation by repeatedly calling a function func.
    ArtistAnimation Animation using a fixed set of Artist objects.

    这里我们只介绍第一种方式FuncAnimation,第二种方式可以自己尝试查阅官网示例。

    无论哪种方式,都需要我们导入matplotlibanimation动画模块:

    from matplotlib import animation
    
    FuncAnimation方式

    FuncAnimation这种方式实现的思路中,包含了2个关键信息点,可以理解为一静一动

    第1点:静态,就是要告诉FuncAnimation对象,你要绘制的动态图像的初始状态,这个一般是自定义一个初始化函数。形如:

    # 初始图像
    def init():
        line.set_ydata(np.sin(x))
        return line,
    

    第2点:动态,也就是要告诉FuncAnimation对象,你要绘制的动态图像的要怎么动,也即如何更新。这个也是自定义一个更新函数来告诉该告诉FuncAnimation对象。形如:

    # 更新图片
    def update(i):
        line.set_ydata(np.sin(x + i/10.0))
        return line,
    

    理解了以上2点思路后,我们就可以把上面自定义的2个函数,告诉FuncAnimation对象了,通过参数传递的形式告诉,形如:

    ani = animation.FuncAnimation(fig=fig,
                                  init_func=init,
                                  func=update,
                                  frames=1000,
                                  interval=1,
                                  blit=False)
    

    fig=fig表示图像figure对象;
    init_func=init:传入的init是一个函数,表示初始化图像;
    func=update传入的update是一个函数,表示要绘制的图像如何动,这个update函数接收一个形参,FuncAnimation对象会每经过interval的时间后会调用该函数,以实现动态绘制;
    frames=1000表示动画一个周期由多少帧组成;
    interval=1表示帧间隔,单位毫秒;
    blit=False表示是否更新所有点;

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import animation
    
    # 动态作图
    fig, ax = plt.subplots()
    x = np.arange(-2 * np.pi, 2 * np.pi, .01)
    line, = ax.plot(x, np.sqrt(x))
    
    
    # 更新图片
    def update(i):
        line.set_ydata(np.sin(x + i/10.0))
        return line,
    
    
    # 初始图像
    def init():
        line.set_ydata(np.sin(x))
        return line,
    
    
    # 动画
    ani = animation.FuncAnimation(fig=fig,
                                  func=update,
                                  init_func=init,
                                  frames=1000,
                                  interval=1,
                                  blit=False)
    # 显示网格
    plt.grid(True)
    
    # 显示图像
    plt.show()
    

    运行结果:


    动态作图

    【提示】
    如果你在用PyCharm开发工具开发,遇到动画动不了,而代码也没有问题,则可以参考另一篇《解决pycharm 无法显示动态图片matplotlib animation》

    小结

    本文学习matplotlib如何可视化数据,这对于后面学习TensorFlow非常有帮助。

    相关文章

      网友评论

        本文标题:47.Python编程:matplotlib详解

        本文链接:https://www.haomeiwen.com/subject/gjylaftx.html