Matplotlib 简明教程

Matplotlib 可以说是最常用的 Python 绘图模块,其实现了许多类似 Matlab 中的函数,可以帮助用户轻松获得高质量的图形。

Pyplot

matplotlib.pyplot 提供了一系列与 Matlab 绘图命令对应的函数,如果你熟悉 Matlab 绘图将很容易上手。

1
2
# 使用 Jupyter notebook 时在开头添加如下命令使图形嵌入当前页面
%matplotlib inline

绘制简单折线:

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt

plt.figure() # 创建一个新的图

plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) # 传入一些 x 和 y 的值来绘制折线
plt.title('Line Chart: Polyline') # 设置标题
plt.xlabel('x') # 设置 x 轴标签文字
plt.ylabel('y') # 设置 y 轴标签文字

plt.show() # 显示图形

image

plot() 不仅支持 list,还可使用 numpy 数组(实际上其内部会将所有的输入序列转换为 numpy 数组):

1
2
3
4
5
6
import numpy as np

x = np.linspace(-5, 5, 128)
y = x ** 2
plt.plot(x, y, 'r')
plt.show()

image

前面的例子通过第三个参数指定了线的颜色,而没有使用 Matplotlib 的默认配置。很多情况下,Matplotlib 的默认配置就够用了,但如果你想进行自定义,你可以调整大多数的默认配置,包括图片大小、线宽、颜色、样式、坐标轴、网格、文字与字体属性等。设置的方式在本节后面的内容中详细介绍。

plot()可以输入任意多的参数,因而支持在同一个命令中绘制多条不同的线:

1
2
3
x = np.arange(0, 5, 0.2)
plt.plot(x, x, 'r', x, x**2, 'g', x, x**3, 'b')
plt.show()

image

设置线的属性

设置线的属性有多种方式:

  • 使用plot()时通过关键参数进行设置
  • 使用plot()时通过样式字符串进行设置
  • 通过Line2D对象的方法进行设置
  • 使用setp()批量设置

使用关键参数

可以通过指定关键参数来设定线的相关属性,对应的其实就是 Line2D 的属性。

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)
y = np.sin(x)

# 使用关键参数,设置样式为宽度2.0的蓝色实线
plt.plot(x, y, color="blue", linewidth=2.0, linestyle="-")
plt.show()

image

以下链接是颜色、线样式、Marker样式的相关参考:

使用样式字符串

样式字符串支持用简洁的代码进行基本属性的设置,样式字符串的形式如下:

1
fmt = '[color][marker][line]'

示例:

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)
y = np.sin(x)

# 使用样式字符串,设置颜色为绿色,设置Marker样式为点
plt.plot(x, y, "g.")
plt.show()

image

常用的颜色

字符 颜色
‘b’ blue
‘g’ green
‘r’ red
‘c’ cyan
‘m’ magenta
‘y’ yellow
‘k’ black
‘w’ white

常用的线样式

字符 样式
‘-‘ 实线
‘—‘ 虚线
‘-.’ 点划线
‘:’ 点线

常用的Marker

字符 样式
‘.’ point marker
‘,’ pixel marker
‘o’ circle marker
‘v’ triangle_down marker
‘^’ triangle_up marker
‘<’ triangle_left marker
‘>’ triangle_right marker
‘1’ tri_down marker
‘2’ tri_up marker
‘3’ tri_left marker
‘4’ tri_right marker
‘s’ square marker
‘p’ pentagon marker
‘*’ star marker
‘h’ hexagon1 marker
‘H’ hexagon2 marker
‘+’ plus marker
‘x’ x marker
‘D’ diamond marker
‘d’ thin_diamond marker

使用 Line2D 对象

1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)
y = np.sin(x)

# 使用 Line2D 对象
line, = plt.plot(x, y)
line.set_color("#FF0000") # 设置颜色为红色
line.set_linewidth(2.0) # 线宽为2.0
line.set_linestyle(":") # 样式为点线
plt.show()

image

更多线的属性设置请参考 matplotlib.lines.Line2D

批量设置

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)
y = np.sin(x)

lines = plt.plot(x, np.sin(x), x, np.cos(x))

# 批量设置样式为宽度2.0的蓝色点划线
plt.setp(lines, color='b', linewidth=2.0, linestyle="--")
plt.show()

image

设置图形属性

设置图形的大小、分辨率:

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)
y = np.sin(x)

# 设置图像大小
plt.figure(figsize=(8,3), dpi=100)

# 使用蓝色实线绘制函数曲线
plt.plot(x, y, color="blue", linewidth=2.0, linestyle="-")

plt.show()

image

更多图形属性设置请参考 matplotlib.figure.Figure

添加图例

下面的例子在左下角添加图例,图例的文字在调用plot()时由 label 参数值指定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)

# 设置图像大小和分辨率
plt.figure(figsize=(8,3), dpi=100)

# 分别用蓝色实线和红色虚线绘制函数曲线,并设定 label
plt.plot(x, np.sin(x), color="blue", linewidth=2.0, linestyle="-", label="sin")
plt.plot(x, np.cos(x), color="red", linewidth=2.0, linestyle="--", label="cos")

# 添加图例
plt.legend(loc='lower left', frameon=False)

plt.show()

image

更多图例的细节请参考 matplotlib.pyplot.legend

添加文字

我们可使用text()在指定位置添加文字,xlabel(), ylabel()title()可以指定坐标轴和标题的文字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)

plt.figure(figsize=(8,3), dpi=100)
plt.plot(x, np.sin(x), color="blue", linewidth=2.0, linestyle="-", label="sin")
plt.plot(x, np.cos(x), color="red", linewidth=2.0, linestyle="--", label="cos")
plt.legend(loc='lower left', frameon=False)

# 添加文字标注
plt.xlabel("x")
plt.ylabel("y")
plt.title('Line Chart')

plt.show()

image

更多使用文字的示例请参考官方指南-文本

使用数学表达式

另外,Matplotlib 支持 LaTeX,可以很方便地在两个 $ 符号之间用 LaTeX 表示数学公式。修改前面的例子如下:

1
2
3
4
5
6
7
8
9
10
plt.figure(figsize=(8,3), dpi=100) 
plt.plot(x, np.sin(x), color="blue", linewidth=2.0, linestyle="-", label=r"$sin(\theta)$")
plt.plot(x, np.cos(x), color="red", linewidth=2.0, linestyle="--", label=r"$cos(\theta)$")
plt.legend(loc='lower left', frameon=False)

# 使用数学表达式
plt.xlabel(r"$\theta$")
plt.text(2.2, 0.9, r"$sin(\frac{\pi}{2})=1$")

plt.show()

image

更多使用 Latex 的示例请参考 官方指南-Latex

添加注记

在前面的例子基础上加入下面的代码:

1
2
3
4
5
# 添加注记
plt.annotate(r"$sin(\frac{\pi}{2})=-1$", xy=(-np.pi/2, -1), xytext=(-2.3, -0.5),
arrowprops=dict(facecolor='black', shrink=0.0))

plt.show()

image

更多使用注记的示例请参考官方指南-注记

设置坐标轴

使用xlim()ylim()可以控制坐标轴的范围。xticks()yticks()可以控制坐标轴上的标记。通过pyplot.gca()可以获得 Axes 对象,设置Axes的属性可以进行更多的控制。

坐标轴范围、坐标轴标记

设置坐标轴范围以及标记:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2*np.pi, 2*np.pi, 96)

plt.figure(figsize=(8,3), dpi=100)
plt.plot(x, np.sin(x), color="blue", linewidth=2.0, linestyle="-", label=r"$sin(\theta)$")
plt.plot(x, np.cos(x), color="red", linewidth=2.0, linestyle="--", label=r"$cos(\theta)$")
plt.legend(loc='lower left', frameon=False)

# 指定坐标轴范围
plt.xlim([-2*np.pi*1.1, 2*np.pi*1.1])
plt.ylim([-1*1.2, 1*1.2])
# 另一种指定坐标轴范围的方式
#plt.axis([-2*np.pi*1.1, 2*np.pi*1.1, -1*1.2, 1*1.2])

# 设置坐标轴标记
xlabels = [r'$-2\pi$', r'$-3\pi/2$', r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$', r'$+3\pi/2$', r'$+2\pi$']
plt.xticks(np.linspace(-2*np.pi, 2*np.pi, 9), xlabels)
plt.yticks([-1, 0, +1], [r'$-1$', r'$0$', r'$+1$'])

plt.show()

image

移动坐标轴

添加下面的代码调整坐标轴的位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xlabels = [r'$-2\pi$', r'$-3\pi/2$', r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$', r'$+3\pi/2$', r'$+2\pi$']
plt.xticks(np.linspace(-2*np.pi, 2*np.pi, 9), xlabels)
plt.yticks([-1, +1], [r'$-1$', r'$+1$'])

# 移动坐标轴
ax = plt.gca()
ax.spines['right'].set_color('none') # 隐藏右侧的轴线
ax.spines['top'].set_color('none') # 隐藏顶部的轴线
ax.xaxis.set_ticks_position('bottom') # 指定底部轴线显示标记
ax.spines['bottom'].set_position(('data',0)) # 设置底部轴线的位置(横轴)
ax.yaxis.set_ticks_position('left') # 指定左侧轴线显示标记
ax.spines['left'].set_position(('data',0)) # 设置左侧轴线的位置(纵轴)

plt.show()

image

子图

有多种方式绘制一个拥有多个子图的图形:

  • 使用 pyplot 的subplots()命令
  • 使用 pyplot 的subplot2grid()命令
  • 使用 gridspec 模块
  • 使用 Figure 对象的add_axes()方法

subplots

绘制一个含有两个子图的图形:

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-2*np.pi, 2*np.pi, 96)

plt.figure(figsize=(8,3), dpi=100)

plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x), "b-")

plt.subplot(2, 1, 2)
plt.plot(x, np.cos(x), "r--")
plt.show()

image

两行两列四个子图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
x1 = np.linspace(-2*np.pi, 0, 96)
x2 = np.linspace(0, 2*np.pi, 96)

plt.figure(figsize=(8,4), dpi=100)

plt.subplot(2, 2, 1)
plt.plot(x1, np.sin(x1), "b-")
plt.xticks(np.linspace(-2*np.pi, 0, 5), [r'$-2\pi$', r'$-3\pi/2$', r'$-\pi$', r'$-\pi/2$', r'$0$'])

plt.subplot(2, 2, 2)
plt.plot(x2, np.sin(x2), "b-")
plt.xticks(np.linspace(0, 2*np.pi, 5), [r'$0$', r'$\pi/2$', r'$\pi$', r'$3\pi/2$', r'$2\pi$'])

plt.subplot(2, 2, 3)
plt.plot(x1, np.cos(x1), "r--")
plt.xticks(np.linspace(-2*np.pi, 0, 5), [r'$-2\pi$', r'$-3\pi/2$', r'$-\pi$', r'$-\pi/2$', r'$0$'])

plt.subplot(2, 2, 4)
plt.plot(x2, np.cos(x2), "r--")
plt.xticks(np.linspace(0, 2*np.pi, 5), [r'$0$', r'$\pi/2$', r'$\pi$', r'$3\pi/2$', r'$2\pi$'])

plt.show()

image

其他绘制子图的方式请参考官方指南-布局

其他图形

更多的图形请参考 https://matplotlib.org/gallery.html

动画

可以使用下面两种 Animation 类来实现动画:

  • FuncAnimation - 通过反复调用指定的函数func来制作动画
  • ArtistAnimation - 通过一个固定的Artist对象集合来实现动画

生成的动画可使用Animation.saveAnimation.to_html5_video保存(可能需要安装 ffmpeg)。

动画的具体使用请参考 https://matplotlib.org/api/animation_api.html

参考资料

https://matplotlib.org/

https://matplotlib.org/users/beginner.html

https://matplotlib.org/users/tutorials.html

https://matplotlib.org/gallery.html

https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html

http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-4-Matplotlib.ipynb

http://www.labri.fr/perso/nrougier/teaching/matplotlib/

http://www.scipy-lectures.org/intro/matplotlib/index.html