现在关注最常见的绘制曲线图需求。

绘制曲线

使用 Axesplot 方法绘制曲线图,假设 x,y,x2,y2 都是一维的数组,那么可以使用下面几种方式绘制曲线

1
2
3
4
5
ax.plot(y) # 一条散点连成的曲线,横坐标取从0开始的整数,纵坐标取自y

ax.plot(x,y) # 一条散点连成的曲线,横坐标取自x,纵坐标取自y

ax.plot(x,y,x2,y2) # 两条曲线,第一条横坐标取自x,纵坐标取自y,第二条横坐标取自x2,纵坐标取自y2

还可以附加一些细节参数,例如颜色,曲线样式,图例等,下面依次介绍。

颜色

几个常用的颜色及其缩写如下:

  • 蓝色 blue-b
  • 绿色 green-g
  • 红色 red-r
  • 白色 white-w
  • 黑色 black-k(因为b已经被blue占用)
  • 金黄色 yellow-y
  • 蓝绿色(青色)cyan-c
  • 品红色 magenta-m

可以使用关键字参数设置固定的颜色 color='red' 或者使用十六进制的颜色编码如 color='#32CD32'。支持如下的简写:

  • 将常用颜色使用简写,例如 color='r'
  • 将关键字 color 简写为 c,例如 c='r'

例如:(这里白色的线和背景重了看不出来)

1
2
3
4
5
6
7
8
9
fig, ax = plt.subplots(figsize=(7, 5))

data = 10 + 0.4 * np.random.randn(9, 100)
colors = ["blue", "green", "red", "white", "black", "yellow", "cyan", "m",'#32CD32']

for i, item in enumerate(colors):
ax.plot(data[i] - i, color=item, label=item)

ax.legend()

曲线样式

支持的曲线样式如下:

  • 实线(默认):solid,简写 -
  • 短虚线(点虚线):dotted,简写 :
  • 长虚线(破折线):dashed,简写 --
  • 长短交错虚线(点划线):dashdot,简写 -.
  • 不画线(什么也没有):None,简写 "" 或者 ''

可以使用关键字参数 linestyle='dotted' 设置曲线样式。支持如下的简写:

  • 将曲线样式使用简写,例如 linestyle=':'
  • 将关键字 linestyle 简写为 ls,例如 ls='-.'

例如

1
2
3
4
5
6
7
8
9
10
11
fig, ax = plt.subplots(figsize=(7, 5))


style = ["solid", "dotted", "dashed", "dashdot", "None" ]

data = 10 + 0.4 * np.random.randn(len(style), 100)

for i, item in enumerate(style):
ax.plot(data[i] - i,linestyle=item,label=item)

ax.legend()

还支持调整线的宽度(linewidth,简称 lw),线宽的默认值是 1.5,例如

1
2
3
4
5
6
fig, ax = plt.subplots(figsize=(4, 3))

data = np.sin(np.linspace(0, 2 * np.pi, 100))

ax.plot(data,lw=5)
ax.plot(data+0.5)

绘图标记

常用的点的标记如下:

  • '.'
  • 像素点 ','
  • 实心圆 'o' 字母 o
  • 星号 '*'
  • 乘号 'x'
  • 加号 '+'
  • 菱形 'D',瘦菱形 'd'
  • 正方形 's'
  • 三角形 '^','<','v','>'(不同的四个朝向)

可以使用关键字参数 marker='*' 设置绘图标记。

例如:(这里像素点根本看不清)

1
2
3
4
5
6
7
8
9
10
11
fig, ax = plt.subplots(figsize=(7, 5))

markers = [".", ",", "o", "*", "x", "D", "d", "s", "^"]
data = np.sin(np.linspace(0, 2 * np.pi, 10 * len(markers)))

ax.plot(data)

for i, item in enumerate(markers):
ax.plot(i * 10, data[i * 10], label=item, marker=item)

ax.legend()

关于绘图标记,我们还可以指定标记的大小(markersize 简写 ms),内部填充颜色(markerfacecolor 简写 mfc),边框填充颜色(markeredgecolor 简写 mec),例如

1
2
3
4
5
fig, ax = plt.subplots(figsize=(4, 3))

data = np.random.randn(7)

ax.plot(data, marker = 'o', ms = 10, mec = 'r')

注:使用 linestyle='',marker='o' 可以达到散点图的效果,并且可能比专门的散点图 plt.scatter 更好,例如

1
2
3
4
5
fig, ax = plt.subplots(figsize=(4, 3))

data = np.random.randn(7)

ax.plot(data, ls='',marker = 'o', ms = 5)

fmt 参数

对于曲线常用的标记、样式、颜色三种设置,可以把相应的简写合并为一个字符串参数,这里每一个部分都是可选的,顺序也是任意的。

1
'[marker][line][color]'

例如:

  • o:r 圆点,点虚线,红色
  • go-- 绿色,破折线,绿色

示例如下

1
2
3
4
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 20)
ax.plot(x,np.sin(x),'o:r')

图像细节

标题和轴标签

支持两层标题:Figure 可以使用 suptitle 设置标题,Axes 可以使用 set_title 设置标题。

例如

1
2
3
4
5
6
7
8
9
10
fig, axes = plt.subplots(1,2,figsize=(7, 3))

x = np.linspace(0, 2 * np.pi, 100)

axes[0].plot(x,np.sin(x))
axes[1].plot(x,np.cos(x))

axes[0].set_title("sin(x)")
axes[1].set_title("cos(x)")
fig.suptitle("fig-title")

可以给每一个坐标轴都可以加上轴标签:

1
2
ax.set_xlabel("x")
ax.set_ylabel("y")

例如

1
2
3
4
5
6
7
8
9
10
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 100)

ax.plot(x,np.sin(x))

ax.set_xlabel("x")
ax.set_ylabel("y")

ax.set_title("sin(x)")

对于标题和轴标签这类的文本选项,有很多额外的选项:

  • 位置:例如 loc="left",对于标题和 x 轴包括 "left","center","right" 选项,对于 y 轴包括 "top","center","bottom" 选项,默认都是居中
  • 颜色:例如 color='r'
  • 字体:例如 fontfamily = 'sans-serif',注意默认不支持中文显示。
  • 字体大小:例如 fontsize=18
  • 字体样式:例如 fontstyle='oblique'

图例

对每一条曲线加上 label,然后使用 Axes.legend() 显示图例,注意 legend() 调用必须在所有 label 之后,图例的文字支持简单的 latex。

例如

1
2
3
4
5
6
7
8
9
10
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 100)

ax.plot(x,np.sin(x),label='sin(x)')
ax.plot(x,np.cos(x),label='cos(x)')

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

网格线

函数原型为

1
Axes.grid(visible=None, which='major', axis='both', **kwargs)

其中主要参数:

  • visible 可见性
  • which 绘制主刻度还是辅助刻度的网格线,支持选项 'major','minor','both',默认 'major' 只绘制主刻度的网格线
  • axis 绘制从 x 轴或 y 轴发出的网格线,支持选项 'both','x','y',默认 'both'

可以简单地使用 ax.grid() 开启网格线,还可以指定网格线更复杂的细节(样式,宽度,颜色,透明度 alpha 等)。

例如

1
2
3
4
5
6
7
8
9
10
11
12
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 100)

ax.plot(x,np.sin(x),label='sin(x)')
ax.plot(x,np.cos(x),label='cos(x)')

ax.grid(ls=':', lw=1, color='r',alpha=0.3)

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

轴的单位长度比

可以手动设置 x 轴和 y 轴的单位长度的比例,默认是 auto,也就是会根据作图需要自动调整。

1
2
3
4
5
6
7
8
# 自动调整
ax.set_aspect('auto')

# 相等
ax.set_aspect('equal')

# 固定y轴/x轴的单位长度比例
ax.set_aspect(2)

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fig, ax = plt.subplots(figsize=(4, 4))

x = np.linspace(-1,1,100)

ax.plot(x,x,label='$x$')
ax.plot(x,x**2,label='$x^2$')
ax.plot(x,x**3,label='$x^3$')

ax.grid(ls=':', lw=1, color='r',alpha=0.3)

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

ax.set_aspect('equal')

边框隐藏

默认情况下作图会绘制四个边框,有时我们需要去掉某些边框,有两种方案:

  • 设置边框透明度为 0
  • 设置边框颜色为空

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
fig, ax = plt.subplots(figsize=(4, 4))

x = np.linspace(0,1,100)
ax.plot(x,x**2,label='$x^2$')

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

ax.spines['right'].set_alpha(0)
ax.spines['top'].set_color('none')

ax.set_aspect('equal')

坐标轴范围

通常 Axes 的坐标轴具体范围根据数据而来,但是我们也可以指定坐标轴的范围(数据如果不在范围内就不会显示)

1
2
ax.set_xlim(-1,2)
ax.set_ylim(0,3)

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fig, ax = plt.subplots(figsize=(4, 4))

x = np.linspace(-1,1,100)
ax.plot(x,x**2,label='$x^2$')
ax.plot(x,x+1,label='$x+1$')

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

ax.spines['right'].set_alpha(0)
ax.spines['top'].set_color('none')

ax.set_aspect('equal')

ax.set_xlim(-1,2)
ax.set_ylim(0,3)

坐标轴指定刻度

可以指定一条轴上使用哪些刻度,使用 ax.set_xticks 方法传入一个数组。

例如

1
2
3
4
5
6
7
8
9
10
11
12
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 100)

ax.plot(x,np.sin(x),label='sin(x)')
ax.plot(x,np.cos(x),label='cos(x)')

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

ax.set_xticks([0,np.pi,np.pi*2])

坐标轴自定义刻度

我们可以在指定刻度的基础上,将刻度的数值换成另外的文字,使用 ax.set_xticklabels 方法传入一个数组。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 2 * np.pi, 100)

ax.plot(x,np.sin(x),label='sin(x)')
ax.plot(x,np.cos(x),label='cos(x)')

ax.legend()
ax.set_xlabel("xlabel",loc='right')
ax.set_ylabel("ylabel",loc='top')

ax.set_xticks([0,np.pi,np.pi*2])
ax.set_xticklabels(['0','$\pi/2$','$\pi$'])

坐标轴刻度朝向

如下的语句可以使得刻度朝内侧("in"),还支持两个选项:"out" 朝外(默认),"inout" 内外均有。

1
2
mpl.rcParams['xtick.direction'] = 'in'#将x周的刻度线方向设置向内
mpl.rcParams['ytick.direction'] = 'in'#将y轴的刻度方向设置向内

例如

1
2
3
4
5
6
7
8
9
mpl.rcParams['xtick.direction'] = 'in'#将x周的刻度线方向设置向内
mpl.rcParams['ytick.direction'] = 'in'#将y轴的刻度方向设置向内

fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 3, 100)
y = np.exp(x)

ax.plot(x,y)

坐标轴比例

默认的坐标轴比例是线性的,但是我们可以指定对数,双对数等,使用 ax.set_yscale('log') 方法可以设置 y 轴为对数刻度,x 轴也同理。

例如

1
2
3
4
5
6
7
8
9
10
11
12
fig, axes = plt.subplots(1, 2, figsize=(7, 3))

x = np.linspace(0, 3, 100)
y = np.exp(x)

axes[0].plot(x,y)
axes[1].plot(x,y)

axes[0].set_title("linear")
axes[1].set_title("log")

axes[1].set_yscale("log")

添加文字

可以使用 ax.text 向指定的 Axes 对象添加文字,位置是在 Axes 的 xy 轴坐标,文字可以有很多细节的处理,这里略过。

1
2
def text(self, x, y, s, fontdict=None, **kwargs):
...

例如

1
2
3
4
5
6
7
8
9
fig, ax = plt.subplots(figsize=(4, 3))

x = np.linspace(0, 3, 100)
y = np.exp(x)

ax.plot(x,y)

ax.plot(1,np.e,'o:r')
ax.text(1+0.2,np.e-0.2,"(1,e)")

解决中文乱码

使用下面的两行语句可以支持中文字体显示

1
2
mpl.rcParams['font.sans-serif']=['SimHei'] # 支持中文字体
mpl.rcParams['axes.unicode_minus'] = False # 否则负号会显示方块