前言
有时候为了直观,我们需要将数据可视化,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
中的一切元素都可以根据业务需求或个人喜好自定义:弹框的标题、坐标轴位置、坐标轴精度、坐标轴刻度、坐标轴显示或隐藏、绘图的线条样式、线条宽度、线条颜色、图例、注解等所有元素。
【说明】
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
中,完整示例如下:
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)
。此时再运行,会有两个图像弹框,运行结果如下:
坐标轴设置
坐标轴未进行任何设置时,会采用默认设置和自适应,如下:
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
中的c
是color
的首字母。
绘制散点图,示例如下:
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)
运行结果:
有了3D
的figure
,我们就可以在此基础上绘制3D
图像了:ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')
其中:
X
表示3维中的x;
Y
表示3维中的y;
Z
表示3维中的z;
rstride=1
、cstride=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()
运行结果:
说明:
1.为了方便查看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()
运行结果:
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()
上面多子图,一一对应的索引如下:
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()
运行结果:
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()
运行结果:
动态图像
制作动态图像,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
,第二种方式可以自己尝试查阅官网示例。
无论哪种方式,都需要我们导入matplotlib
的animation
动画模块:
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
非常有帮助。