>>> from env_helper import info; info()
页面更新时间: 2023-06-30 23:20:54
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-9-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

4.1. Matplotlib-绘制精美的图表

matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图。 而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中。 它的文档相当完备,并且 Gallery页面 中有上百幅缩略图,打开之后都有源程序。 因此如果你需要绘制某种类型的图,只需要在这个页面中浏览/复制/粘贴一下,基本上都能搞定。

本章节作为matplotlib的入门介绍,将较为深入地挖掘几个例子,从中理解和学习matplotlib绘图的一些基本概念。

4.1.1. 快速绘图

matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表。 让我们先来看一个简单的例子:

>>> %matplotlib inline
>>>
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = np.linspace(0, 10, 1000)
>>> y = np.sin(x)
>>> z = np.cos(x**2)
>>> plt.figure(figsize=(8,4))
>>> plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
>>> plt.plot(x,z,"b--",label="$cos(x^2)$")
>>> plt.xlabel("Time(s)")
>>> plt.ylabel("Volt")
>>> plt.title("PyPlot First Example")
>>> plt.ylim(-1.2,1.2)
>>> plt.legend()
>>> plt.show()
_images/sec01_basic_5_0.png

调用pyplot库快速将数据绘制成曲线图

matplotlib中的快速绘图的函数库可以通过如下语句载入:

>>> import matplotlib.pyplot as plt

4.1.2. pylab模块

matplotlib还提供了名为pylab的模块,其中包括了许多numpy和pyplot中常用的函数,方便用 户快速进行计算和绘图,可以用于IPython中的快速交互式使用。

接下来调用figure创建一个绘图对象,并且使它成为当前的绘图对象。

>>> import matplotlib.pyplot as plt
>>> plt.figure(figsize=(8,4))
<Figure size 800x400 with 0 Axes>
<Figure size 800x400 with 0 Axes>

也可以不创建绘图对象直接调用接下来的plot函数直接绘图,matplotlib会为我们自动创建一个绘图对 象。如果需要同时绘制多幅图表的话,可以是给figure传递一个整数参数指定图标的序号,如果所指定 序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。 通过figsize参数可以指定绘图对象的宽度和高度,单位为英寸;dpi参数指定绘图对象的分辨率,即每 英寸多少个像素,缺省值为80。因此本例中所创建的图表窗口的宽度为880 = 640像素。 但是用工具栏中的保存按钮保存下来的png图像的大小是800400像素。这是因为保存图表用的函数 savefig使用不同的DPI配置,savefig函数也有一个dpi参数,如果不设置的话,将使用matplotlib配置 文件中的配置,此配置可以通过如下语句进行查看,关于配置文件将在后面的章节进行介绍:

>>> import matplotlib
>>> matplotlib.rcParams["savefig.dpi"]
'figure'

下面的两行程序通过调用plot函数在当前的绘图对象中进行绘图:

>>> plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
>>> plt.plot(x,z,"b--",label="$cos(x^2)$")
>>> plt.show()
_images/sec01_basic_15_0.png

plot函数的调用方式很灵活,第一句将x,y数组传递给plot之后,用关键字参数指定各种属性:

  • label : 给所绘制的曲线一个名字,此名字在图示(legend)中显示。只要在字符串前后添加 $ 符 号,matplotlib就会使用其内嵌的latex引擎绘制的数学公式。

  • color : 指定曲线的颜色

  • linewidth : 指定曲线的宽度

第二句直接通过第三个参数 b-- 指定曲线的颜色和线型,这个参数称为格式化参数,它能够通过一些易记的符号快速指定曲线的样式。 其中 b 表示蓝色,-- 表示线型为虚线。在IPython中输入 plt.plot ? 可以查看格式化字符串的详细配置。

接下来通过一系列函数设置绘图对象的各个属性。在此之前要注意,在交互环境下, 绘图函数除了绘图,还有清空内存画板的作用。 所以为了使用前面的数据,需要重新进行绘制,如下:

>>> plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
>>> plt.plot(x,z,"b--",label="$cos(x^2)$")
>>> plt.xlabel("Time(s)")
>>> plt.ylabel("Volt")
>>> plt.title("PyPlot First Example")
>>> plt.ylim(-1.2,1.2)
>>> plt.legend()
<matplotlib.legend.Legend at 0x7f6cd0e3fe90>
_images/sec01_basic_18_1.png
  • xlabel : 设置X轴的文字

  • ylabel : 设置Y轴的文字

  • title : 设置图表的标题

  • ylim : 设置Y轴的范围

  • legend : 显示图示

最后调用 plt.show() 显示出我们创建的所有绘图对象。

4.1.3. 配置属性

matplotlib所绘制的图的每个组成部分都对应有一个对象,我们可以通过调用这些对象的属 性设置方法 set_*或者pyplot的属性设置函数 setp设置其属性值。例如plot函数返回一个 matplotlib.lines.Line2D 对象的列表,下面的例子显示如何设置Line2D对象的属性:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = np.arange(0, 5, 0.1)
>>> line, = plt.plot(x, x*x) # plot返回一个列表,通过line,获取其第一个元素
>>> # 调用Line2D对象的set_*方法设置属性值
>>> line.set_antialiased(False)
>>> # 同时绘制sin和cos两条曲线,lines是一个有两个Line2D对象的列表
>>> lines = plt.plot(x, np.sin(x), x, np.cos(x)) #
>>> # 调用setp函数同时配置多个Line2D对象的多个属性值
>>> plt.setp(lines, color="r", linewidth=2.0)
>>> plt.setp(line,linewidth=1.0)
>>> plt.show()
_images/sec01_basic_21_0.png

这段例子中,通过调用Line2D对象line的set_antialiased方法,关闭对象的反锯齿效果。或者通过调 用plt.setp函数配置多个Line2D对象的颜色和线宽属性。 同样我们可以通过调用Line2D对象的get_*方法,或者plt.getp函数获取对象的属性值:

>>> line.get_linewidth()
1.0
>>> plt.getp(lines[0], "color") # 返回color属性
'r'
>>> plt.getp(lines) # 输出全部属性
agg_filter = None
alpha = None
animated = False
antialiased or aa = True
bbox = Bbox(x0=0.0, y0=-0.9999232575641009, x1=4.9, y1=0....
children = []
clip_box = TransformedBbox(     Bbox(x0=0.0, y0=0.0, x1=1.0, ...
clip_on = True
clip_path = None
color or c = r
dash_capstyle = butt
dash_joinstyle = round
data = (array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0....
drawstyle or ds = default
figure = Figure(640x480)
fillstyle = full
gapcolor = None
gid = None
in_layout = True
label = _child1
linestyle or ls = -
linewidth or lw = 2.0
marker = None
markeredgecolor or mec = r
markeredgewidth or mew = 1.0
markerfacecolor or mfc = r
markerfacecoloralt or mfcalt = none
markersize or ms = 6.0
markevery = None
mouseover = False
path = Path(array([[ 0.        ,  0.        ],        [ 0...
path_effects = []
picker = None
pickradius = 5
rasterized = False
sketch_params = None
snap = None
solid_capstyle = projecting
solid_joinstyle = round
tightbbox = Bbox(x0=102.54545454545455, y0=69.6, x1=553.454545...
transform = CompositeGenericTransform(     TransformWrapper(  ...
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = Bbox(x0=102.54545454545455, y0=69.6, x1=553.454545...
xdata = [0.  0.1 0.2 0.3 0.4 0.5]...
xydata = [[0.         0.        ]  [0.1        0.09983342] ...
ydata = [0.         0.09983342 0.19866933 0.29552021 0.389...
zorder = 2

注意 getp 函数只能对一个对象进行操作,它有两种用法:

  • 指定属性名:返回对象的指定属性的值

  • 不指定属性名:打印出对象的所有属性和其值

matplotlib 的整个图表为一个Figure对象,此对象在调用 plt.figure 函数时返回, 我们也可以通过 plt.gcf 函数获取当前的绘图对象:

>>> f = plt.gcf()
>>> plt.getp(f)
agg_filter = None
alpha = None
animated = False
axes = []
children = [<matplotlib.patches.Rectangle object at 0x7f6cd0d...
clip_box = None
clip_on = True
clip_path = None
constrained_layout = False
constrained_layout_pads = (None, None, None, None)
default_bbox_extra_artists = []
dpi = 100.0
edgecolor = (1.0, 1.0, 1.0, 1.0)
facecolor = (1.0, 1.0, 1.0, 1.0)
figheight = 4.8
figure = Figure(640x480)
figwidth = 6.4
frameon = True
gid = None
in_layout = True
label =
layout_engine = None
linewidth = 0.0
mouseover = False
path_effects = []
picker = None
rasterized = False
size_inches = [6.4 4.8]
sketch_params = None
snap = None
tight_layout = False
tightbbox = Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8)
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True
window_extent = TransformedBbox(     Bbox(x0=0.0, y0=0.0, x1=6.4, ...
zorder = 0
<Figure size 640x480 with 0 Axes>

Figure对象有一个 axes 属性,其值为 AxesSubplot 对象的列表, 每个 AxesSubplot 对象代表图表中的一个子图,前面所绘制的图表只包含一个子图,当前子图也可以通过 plt.gca 获得:

>>> plt.getp(f, "axes")
[]
>>> plt.gca()
<AxesSubplot: >
_images/sec01_basic_30_1.png

用plt.getp可以发现AxesSubplot对象有很多属性,例如它的lines属性为此子图所包括的 Line2D 对象 列表:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = np.arange(0, 5, 0.1)
>>>
>>> # plot函数返回一个 matplotlib.lines.Line2D 对象的列表
>>> line, = plt.plot(x, x*x) # plot返回一个列表,通过line,获取其第一个元素
>>> line.set_antialiased(False) # 调用Line2D对象的set_*方法设置属性值
>>>
>>> # 同时绘制sin和cos两条曲线,lines是一个有两个Line2D对象的列表
>>> lines = plt.plot(x, np.sin(x), x, np.cos(x))
>>> # 调用setp函数同时配置多个Line2D对象的多个属性值
>>>
>>> alllines = plt.getp(plt.gca(), "lines")
>>> alllines
<a list of 3 Line2D objects>
_images/sec01_basic_32_1.png
>>> alllines[0] == line
True

其中的第一条曲线就是最开始绘制的那条曲线。

通过这种方法我们可以很容易地查看对象的属性和它们之间的包含关系,找到需要配置的属性。