前言
上一节我们提到,matplotlib
绘图有两种风格
- 显式创建图形与轴空间,并在其上调用方法的OO风格
- 依靠
pyplot
自动创建和管理图形和轴,并使用pyplot
函数进行绘图的plt
风格。
我们上一节中的示例代码一第一种方式为主,这一节我们介绍第二种方式,也就是pyplot
pyplot介绍
matplotlib.pyplot
是一些函数的集合,使matplotlib
像MATLAB
一样工作。每个绘图函数对图形(figure)进行一些更改:例如,创建图形,在图形中创建绘图区域,在绘图区域绘制一些线条,使用标签装饰绘图等。
在matplotlib.pyplot
中,多种状态通过函数之间的调用来保存,以便跟踪诸如当前图形和绘图区域之类的东西。并且绘图函数始终指向当前轴域(请注意,这里和文档中的大多数位置中的『轴域』(axes)是指图形的一部分(坐标轴围成的区域),而不是指代多于一个轴的严格数学术语)。
通过pyplot
绘制图像是非常迅速的。plt.plot
是有返回值的,返回的是线的实例列表。只不过这里我们并不需要获得返回值
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdyFhxV5-1644763593009)(D:\2021-autumn\matplotlib\图像\pyplot\output.png)]
我们明明只传入了一个列表,为什么绘制出了 x 的范围和 y 的范围呢?如果我们向plot中只传入了一个列表或数组,matplotlib会认为这个序列代表的是 y 的值,并且为我们自动产生 x 的值。因为 python 中的范围是从 0 开始的,且默认的 x 向量与 y 向量具有相同的长度。因此,生成的 x 是[0,1,2,3]。
plot是一个通用函数,并且可以接受任意数量的参数。如果要绘制 x 和 y,我们可以写成
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
-
plot只能画二维图像,我们绘制 x-y 时需要成对输入(每一对是一条线)。如果有单个的序列,则会被认为是 y 的值,并且自动生成 x。
plt.plot([1, 2, 3, 4], [1, 4, 9, 16],[1, 2, 3, 4],[1, 2, 3, 4])
设置plot的风格
对于每一对 x,y 参数,都有可选的第三个参数(格式字符串)来控制颜色和绘制的线的类型。格式字符串的字母和符号来自 MATLAB
,并且将颜色字符串与线型字符串连接在一起。默认格式字符串为"b-"
,它是一条蓝色实线。例如,要绘制红色圆圈,我们可以写成
plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()
例子中的axis()函数的输入是[xmin, xmax, ymin, ymax]
,用于指定轴域的可视范围。
如果matplotlib
仅限于使用列表,它对于数字处理是相当无用的。通常,我们将会使用numpy
数组。事实上,所有序列都会在内部被转换成numpy
数组。
下面的例子演示了使用数组在一个函数调用中绘制具有不同格式样式的几条线。
import numpy as np# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)# red dashes, blue squares and green triangles
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()
通过关键词字符串绘制
在某些情况下,数据的格式允许我们使用字符串访问特定的变量。比如numpy.recarray
或者pandas.DataFrame
。
Matplotlib
允许我们使用data关键字参数提供这样的对象。如果提供,那么我们可以用这些变量对应的字符串生成图形。
data = {
'a': np.arange(50),'c': np.random.randint(0, 50, 50),'d': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100plt.scatter('a', 'b', c='c', s='d', data=data) #c:color s:size
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()
通过类别变量绘图
names = ['group_a', 'group_b', 'group_c']
values = [1, 10, 100]plt.figure(figsize=(9, 3))plt.subplot(131)
plt.bar(names, values)
plt.subplot(132)
plt.scatter(names, values)
plt.subplot(133)
plt.plot(names, values)
plt.suptitle('Categorical Plotting')
plt.show()
plt.bar()
函数绘制条形图,各种参数如下(上面的names是x参数)
参数 | 说明 | 类型 |
---|---|---|
x | x坐标 | int,float |
height | 条形的高度 | int,float |
width | 线条的宽度 | 0~1,默认是0.8 |
botton | 条形的起始位置 | 也就是y轴的起始坐标 |
align | 条形的中心位置 | “center”,"lege"边缘 |
color | 条形的颜色 | “r”,“b”,“g”,“#123465",默认的颜色是“b” |
edgecolor | 边框的颜色 | 同上 |
linewidth | 边框的宽度 | 像素,默认无,int |
tick_label | 下标的标签 | 可以是元组类型的字符组合 |
log | y轴使用科学计算法表示 | bool |
orientation | 是竖直条还是水平条 | 竖直:“vertical”,水平条:“horizontal” |
控制线条属性
线条有很多可以控制的属性:线宽,线条样式,反锯齿化等。下面有几种可以控制线条属性的方式
-
使用关键词参数
plt.plot(x, y, linewidth=2.0)
-
使用二维直线实例的设定方法。
plot
返回二维直线对象的列表,例如line1,line2 = plot(x1,y1,x2,y2)
。在下面的代码中,我们假设只有一行,因此返回的列表长度为1(也就是只返回一个二维直线实例)。我们对line
使用元组解构,得到该列表的第一个元素:line, = plt.plot(x, y, '-') #该 line 是一个 Line2D 实例 line.set_antialiased(False) # turn off antialiasing
x = [1, 2, 3] y = [1, 2, 3] line = plt.plot(x, y) #该 line 是一个列表 print(type(line)) >> <class 'list'> print(line) >> [<matplotlib.lines.Line2D object at 0x000001E7FF9495B0>]x = [1, 2, 3] y = [1, 2, 3] line, = plt.plot(x, y) #该 line 是一个 Line2D 实例 print(type(line)) >> <class 'matplotlib.lines.Line2D'> print(line) >> Line2D(_line0)
-
使用
setp()
命令。下面的示例使用MATLAB
风格的命令来设置线条列表上的多个属性。setp()
显而易见地对对象列表或者单个对象工作。我们可以使用python关键词参数或者MATLAB
风格的字符串/值对:lines = plt.plot(x1, y1, x2, y2) #线的对象列表 # use keyword arguments plt.setp(lines, color='r', linewidth=2.0) # or MATLAB style string value pairs plt.setp(lines, 'color', 'r', 'linewidth', 2.0)
下面是可用的二维直线的属性
属性 | 值类型 |
---|---|
alpha |
浮点值 |
animated |
[True / False] |
antialiased or aa |
[True / False] |
clip_box |
matplotlib.transform.Bbox 实例 |
clip_on |
[True / False] |
clip_path |
Path 实例, Transform ,以及Patch 实例 |
color or c |
任何 matplotlib 颜色 |
contains |
命中测试函数 |
dash_capstyle |
['butt' / 'round' / 'projecting'] |
dash_joinstyle |
['miter' / 'round' / 'bevel'] |
dashes |
以点为单位的连接/断开墨水序列 |
data |
(np.array xdata, np.array ydata) |
figure |
matplotlib.figure.Figure 实例 |
label |
任何字符串 |
linestyle or ls |
[ '-' / '--' / '-.' / ':' / 'steps' / ...] |
linewidth or lw |
以点为单位的浮点值 |
lod |
[True / False] |
marker |
[ '+' / ',' / '.' / '1' / '2' / '3' / '4' ] |
markeredgecolor or mec |
任何 matplotlib 颜色 |
markeredgewidth or mew |
以点为单位的浮点值 |
markerfacecolor or mfc |
任何 matplotlib 颜色 |
markersize or ms |
浮点值 |
markevery |
[ None / 整数值 / (startind, stride) ] |
picker |
用于交互式线条选择 |
pickradius |
线条的拾取选择半径 |
solid_capstyle |
['butt' / 'round' / 'projecting'] |
solid_joinstyle |
['miter' / 'round' / 'bevel'] |
transform |
matplotlib.transforms.Transform 实例 |
visible |
[True / False] |
xdata |
np.array |
ydata |
np.array |
zorder |
任何数值 |
要获取一个线的可设置的属性列表,可以使用line或lines作为参数调用setp函数
In [69]: lines = plt.plot([1, 2, 3])In [70]: plt.setp(lines)alpha: floatanimated: [True | False]antialiased or aa: [True | False]...snip
处理多个图形和轴域
MATLAB
和pyplot
具有当前图像和当前轴域的概念。所有的绘图函数都应用在当前的轴域上。函数gca()
返回当前轴域(一个matplotlib.axes.Axes
实例),函数gcf()
返回当前图像(一个matplotlib.figure.Figure
实例)。通常,你不必担心这一点,因为它都是在幕后处理。 下面是一个创建两个子图的脚本。
def f(t):return np.exp(-t) * np.cos(2*np.pi*t)t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)plt.figure()
plt.subplot(211) #两行一列的第一个图
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')plt.subplot(212) #两行一列的第二个图
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()
figure
函数的调用是可选的,因为如果不存在图像的话会创建一个图像。就像没有轴域存在的时候会自动创建一个一样(等价于显式调用subplot
函数)。subplot
函数调用指定 numrows
(行数),numcols
(列数),plot_number
(图的序号)。plot_number
的范围是1~numrows*numcols
。 如果numrows * numcols <10
,则subplot
命令中的逗号是可选的。 因此,子图subplot(211)
与subplot(2, 1, 1)
相同。我们可以创建任意数量的子图和轴。如果要手动放置轴域,即不在矩形网格上,请使用axes()
命令,该命令允许你将axes([left, bottom, width, height])
指定为位置,其中所有值都使用小数(0 到 1)坐标。 手动放置轴域的示例请参见pylab_examples
示例代码:axes_demo.py
,具有大量子图的示例请参见pylab_examples
示例代码:subplots_demo.py
。
我们可以通过利用递增的图像序号,来多次调用figure
函数,从而创建多个图像。当然,每个图都可以包含任意多的轴域和子图:
import matplotlib.pyplot as plt
plt.figure(1) # the first figure
plt.subplot(211) # the first subplot in the first figure
plt.plot([1, 2, 3])
plt.subplot(212) # the second subplot in the first figure
plt.plot([4, 5, 6])plt.figure(2) # a second figure
plt.plot([4, 5, 6]) # creates a subplot() by defaultplt.figure(1) # figure 1 current; subplot(212) still current
plt.subplot(211) # make subplot(211) in figure1 current
plt.title('Easy as 1, 2, 3') # subplot 211 title
我们可以使用clf
清除当前图形,使用cla
清除当前轴域。
如果你正在制作大量的图形,你需要注意一件事:在一个图形用close()
显式关闭之前,该图所需的内存不会完全释放。 删除对图形的所有引用,或使用窗口管理器杀死屏幕上出现的图形的窗口是不够的,因为在调用close()
之前,pyplot
会维护内部引用
处理文本
使用text
可以在任何位置添加文本。xlabel()
,ylabel()
和title()
用于在指定的位置添加文本。
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)# the histogram of the data
n, bins, patches = plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
plt.text
用法介绍- 坐标是根据坐标轴确定的二维空间确定的位置,而不是根据图的尺寸来定义的
# 第一个参数是x轴坐标
# 第二个参数是y轴坐标
# 第三个参数是要显式的内容
# alpha 设置字体的透明度
# family 设置字体
# size 设置字体的大小
# style 设置字体的风格
# wight 字体的粗细
# bbox 给字体添加框,alpha 设置框体的透明度, facecolor 设置框体的颜色
所有的text()
命令返回一个matplotlib.text.Text
实例。 与上面一样,我们可以通过将关键字参数传递到text
函数或使用setp()
来自定义属性:
t = plt.xlabel('my data', fontsize=14, color='red')
在文本中使用数学表达式
matplotlib
在任何文本表达式中接受 TeX 方程表达式。 例如,要在标题中写入表达式,可以编写一个由 $ 包围的 TeX 表达式:
plt.title(r'$\sigma_i=15$')
标题字符串之前的r
很重要 - 它表示该字符串是一个原始字符串,而不是将反斜杠作为 python 转义处理。matplotlib
有一个内置的 TeX 表达式解析器和布局引擎,并且自带了自己的数学字体。因此,我们可以跨平台使用数学文本,而无需安装 TeX。
文本标注
上面的text()
基本命令将文本放置在轴域的任意位置。 文本的一个常见用法是对图的某些特征执行标注,而annotate()
方法提供一些辅助功能,使标注变得容易。 在标注中,有两个要考虑的点:由参数xy
表示的标注位置和xytext
表示的文本位置。 这两个参数都是(x, y)
元组。
ax = plt.subplot()t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = plt.plot(t, s, lw=2)plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5),arrowprops=dict(facecolor='black', shrink=0.05),)plt.ylim(-2, 2)
plt.show()
在本基本样例中,xy
(箭头提示)和xytext
位置(文本位置)都在数据坐标中。还有其他很多种坐标系可供选择。详细信息请参阅标注文本和标注轴域。 更多示例可以在pylab_examples
示例代码:annotation_demo.py
中找到。
对数和其它非线性轴
matplotlib.pyplot
不仅支持线性轴刻度,还支持对数和对数刻度。 如果数据跨越许多数量级,通常会使用它。 更改轴的刻度很容易:
plt.xscale('log')
下面示例显示了四个图,具有相同数据和不同刻度的y
轴。
# Fixing random state for reproducibility
np.random.seed(19680801)# make up some data in the open interval (0, 1)
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))# plot with various axes scales
plt.figure()# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)# symmetric log
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthresh=0.01)
plt.title('symlog')
plt.grid(True)# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "1 - 10^{-3}"
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,wspace=0.35)plt.show()