玩命加载中 . . .

常用技巧-matplotlib包


Matplotlib

Matplotlib是一个易用的python绘图工具包。

图层元素

Matplotlib绘图涉及了多个元素。在了解其用法之前,有必要介绍一下绘图要素的构成。

  • 画布(figure)。可以设置画布大小、分辨率、颜色等等。
  • 坐标图形(axes)。即子图,是图形的展示区域。
  • 轴(axis)。即坐标轴对象。
  • 刻度(tick)。坐标轴上的刻度,包括主刻度、次刻度。

Figure与图层

设置画布大小:plt.figure()

画布,即我们将要绘制内容的区域。常用如下方法设置画布大小:

  • plt.figure(figsize: Tuple)

其中,figsize为元组,接受(width, height)作为输入,而width、height单位均为英寸,它们分别指定了画布的宽度和高度。

绘制图像

matplotlib支持多种图形绘制,包括散点图、折线图、柱状图等等。

绘制线:plt.plot()

  • plt.plot(x: List | np.ndarray, y: List | np.ndarray, …)

这个方法将以折线段将给定的点依次连接起来,是绘图方法中最为常见的。该方法参数较多、功能强大,下面进行逐个介绍。

基本用法

其中参数x为点的横坐标序列($[x_0,x_1,\dots,x_{n-1}]$)、y为点的纵坐标序列($[y_0,y_1,\dots,y_{n-1}]$)。注意,如果参数x缺省,那么它将默认为$[0,1,\dots,n-1]$。

# 准备数据
x = np.linspace(0, 20, 100)
y = np.sin(x)
# 绘图
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.plot(x, y)
plt.title('given x and y')
plt.subplot(1, 2, 2)
plt.plot(y)
plt.title('only given y')
plt.show()
plt.close()

plt.plot()方法基本用法

在深度学习训练完成后,往往存储了每一轮的平均训练损失loss_list,此时可以直接调用plt.plot(loss_list)便可直接绘制训练损失曲线,查看训练情况。

除了上述基本用法中的参数外,plot()还有诸多参数,以实现更加强大的绘图功能。下面对其他常用参数进行说明。

参数color

参数color用于指示绘制线条的颜色,其值可以用英文字符串指定,也可以用十六进制编码指定。下面是几个特殊的基本颜色,它们的英文字符串非常简洁,仅为单个字符。

  • b—-blue,蓝
  • c—-cyan,青
  • g—-green,绿
  • k——black,黑
  • m—-magenta,品红
  • r—-red,红
  • w—-white,白
  • y——yellow,黄

更加详细的颜色字符串见下图。

matplotlib颜色表

color_styles = ['r', 'g', 'b', 'y', 'k', 'm', 'c']
color_labels = ['red', 'green', 'blue', 'yellow', 'black', 'magenta', 'cyan']
for idx, (color, label) in enumerate(zip(color_styles, color_labels)):
    plt.plot(x, y + 2 * idx, color=color, label=label)
plt.legend()
plt.show()
plt.close()

不同颜色的线条

线条样式参数linestyle

参数lienstyle用于指示线条样式,其值可以用英文字符串指定,也可以用标点字符串指定。常见的有四种样式:

  • solid(-),实线,
  • dotted(:),点线
  • dashed(—),破折线
  • dashdot(-.),点划线
line_styles = ['-', ':', '--', '-.']
line_labels = ['solid', 'dotted', 'dashed', 'dashdot']
for idx, (line_style, line_label) in enumerate(zip(line_styles, line_labels)):
    plt.plot(y + 2 * idx, label=line_label, linestyle=line_style)
plt.legend()
plt.title('Plots of different linestyles')
plt.show()
plt.close()

不同形状样式的线条

标记点样式参数marker

参数marker用于指示标记样式,常见的参数值见表。

标记字符 说明 标记字符 说明
‘.’ 点标记 ‘1’ 下花三角标记
‘,’ 像素标记(极小点) ‘2’ 上花三角标记
‘o’ 实心圈标记 ‘3’ 左花三角标记
‘v’ 倒三角标记 ‘4’ 右花三角标记
‘^’ 上三角标记 ’s’ 实心方形标记
‘>’ 右三角标记 ‘p’ 实心五角标记
‘<’ 左三角标记 ‘*’ 星形标记
‘h’ 竖六边形标记 ‘d’ 瘦菱形标记
‘H’ 横六边形标记 ‘\ 垂直线标记
‘+’ 十字标记 ‘D’ 菱形标记
‘x’ x标记
import matplotlib.pyplot as plt 
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 #有中文出现的情况,需要u'内容'
x = np.linspace(0, 20, 20)
y = x * 20
marker_styles = ['.', ',', 'o', '+', 'x', '*', '^']
marker_labels = ['点', '极小点', '实心圈', '十字形', '叉形', '星形', '上三角']
for idx, (marker_style, marker_label) in enumerate(zip(marker_styles, marker_labels)):
    plt.plot(x + 5 * idx, y + 2 * idx, label=marker_label, marker=marker_style)
plt.legend()
plt.title('Plots of different markers')
plt.show()
plt.close()

不同标记样式的线条

格式参数format_string

此处的格式包括上面解释的三部分:

  • 颜色样式color
  • 线条样式linestyle
  • 标记样式marker

将各部分的参数字符拼接起来即可,顺序无所谓。

import matplotlib.pyplot as plt 
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 #有中文出现的情况,需要u'内容'
x = np.linspace(0, 20, 20)
y = x * 20
styles = ['c.:', 'b-^', 'k--+']
labels = ['青,点状,点线', '蓝,上三角,实线', '黑,十字,破折线']
for idx, (style, label) in enumerate(zip(styles, labels)):
    plt.plot(x + 5 * idx, y + 2 * idx, style, label=label)
plt.legend() # 显示标签
plt.title('Plots of different format')
plt.show()
plt.close()

不同格式的线条

标签参数label

label用于指示线条的标签意义。它的用法之前的例子已经给出。但是要注意,需要再次调用plt.legend()显示标签到图片中。

设置轴标签:plt.xlabel()/plt.ylabel()

  • plt.xlabel(xlabel: str)
  • plt.ylabel(ylabel: str)

设置x轴或者y轴的标签,指示其意义,比如x轴表示训练轮数、y轴表示准确率。

设置轴刻度:plt.xticks()/plt.yticks()

  • plt.xticks(ticks: ArrayLike | None = None, labels: Sequence[str] | None = None, rotation: float, **kwargs: Any)
  • plt.yticks(ticks: ArrayLike | None = None, labels: Sequence[str] | None = None, rotation: float, **kwargs: Any)

这个方法允许自定义x轴或者y轴。参数ticks指示了要替换的刻度,labels指示了替换刻度的标签文本,rotation指示了标签旋转的角度。

x = np.linspace(0,10,100)
plt.plot(x, x*x)
a = [1, 2, 3, 4, 5] # 要替换的刻度序列
labels = ['A', 'B', 'C', 'D', 'E'] # 替换的标签文本
plt.xticks(a, labels, rotation=-20) # 顺时针旋转20°
plt.show()
plt.close()

plt.xticks()方法自定义轴

另外,可以设置ticks参数为空列表,从而将该轴省去:

x = np.linspace(0,10,100)
plt.plot(x, x*x)
plt.xticks([])
plt.yticks([])
plt.show()
plt.close()

省略坐标轴的图像

设置轴范围:plt.xlim()/plt.ylim()

  • plt.xlim(bottom: float, top: float)
  • plt.ylim(bottom: float, top: float)

这个方法用于设置轴的刻度显示范围,将轴的刻度显示范围设置为[bottom, top]。

设置标题:plt.title()

  • plt.title(label: str)

用于设置图像标题。

多子图绘制

在一个图形中绘制多个子图,是很关键的绘图技巧,也必须掌握。

基本方法:subplot()

  • subplot(nrow, ncol, index)

划分出nrow×ncol个子图区域,在index位置处绘图。另外,参数列表中的逗号在其数值不超过9时可以省略。

fig = plt.figure()
fig.suptitle('Figure1') # 设置画布总标题

plt.subplot(3,4,1)    #plt.subplot(3, 4, 1)
plt.plot([1,2,3,4])
 
plt.subplot(3,4,12)    #plt.subplot(3, 4, 12)
plt.plot([1,2,3,4])
 
plt.show()

plt.subplot()绘图

同时,每一个子图都可以单独设置标题,同样也是使用plt.title()方法:

# 准备数据
x = np.linspace(0, 20, 80)
y_1 = np.cos(x)
y_2 = x ** 2
y_3 = x
y_4 = np.log(x)
y_list = [y_1, y_2, y_3, y_4]
title_list = ['Cosine function', 'Quadratic function', 'Linear function', 'Logarithm function']
# 绘制多子图
fig = plt.figure()
fig.suptitle('Function curves')
nrows, ncols = 2, 2
for idx in range(nrows * ncols):
    plt.subplot(nrows, ncols, idx+1)
    plt.plot(y_list[idx])
    plt.title(title_list[idx])
plt.show()
plt.close()

绘制最基本的子图

可见,在绘制饱满的多子图时,如果不加布局调整,整个图像观感将会很差。下面再介绍几个布局调整方法。

紧凑布局:plt.tight_layout()

  • plt.tight_layout(pad: float)

这个方法用于调整图中子图的大小,以便轴对象和轴上的标签之间不会重叠。同时,接受参数pad,用于调整图像和子图之间的距离。

# 准备数据
x = np.linspace(0, 20, 80)
y_1 = np.cos(x)
y_2 = x ** 2
y_3 = x
y_4 = np.log(x)
y_list = [y_1, y_2, y_3, y_4]
title_list = ['Cosine function', 'Quadratic function', 'Linear function', 'Logarithm function']
# 绘制多子图
fig = plt.figure()
fig.suptitle('Function curves')
nrows, ncols = 2, 2
for idx in range(nrows * ncols):
    plt.subplot(nrows, ncols, idx+1)
    plt.plot(y_list[idx])
    plt.title(title_list[idx])
plt.tight_layout() # 紧凑布局
plt.show()
plt.close()

紧凑布局下的多子图

另一种方法:subplots()

在正式介绍这个方法之前,有必要引入matplotlib中的一个重要概念:Axes。

Figure和Axes对象说明

也就是说,当我们调用plt方法时,

  1. 将生成一个Figure对象(以绿色显示);
  2. 而Axes对象是通过绘制的折线图(红色显示)隐式生成;
  3. 图中的所有元素(如x和y轴)都在Axes对象中呈现(蓝色显示)

plt.subplots(nrows: int, ncols: int, sharex: bool, sharey: bool) -> tuple[Figure, Any]

这个方法用于创建多个子图,它返回Figure对象和多个子图对象;sharex、sharey分别指示是否共享同一个x轴或者y轴。

# 准备数据
x = np.linspace(0, 20, 80)
y_1 = np.cos(x)
y_2 = x ** 2
y_3 = x
y_4 = np.log(x)
y_list = [y_1, y_2, y_3, y_4]
title_list = ['Cosine function', 'Quadratic function', 'Linear function', 'Logarithm function']
# 绘制多子图
nrows, ncols = 2, 2
fig, axes = plt.subplots(nrows, ncols) # 获取Figure对象和Axes对象
fig.suptitle('Function curves')
for row_id in range(nrows):
    for col_id in range(ncols):
        ax = axes[row_id][col_id] # 获取对应的ax对象
        ax.plot(y_list[row_id*nrows+col_id])
        ax.set_title(title_list[row_id*nrows+col_id])
fig.tight_layout() # 紧凑布局
plt.show()
plt.close()

plt.subplots()方法绘制子图

# 准备数据
x = np.linspace(0, 20, 80)
y_1 = np.cos(x)
y_2 = np.log(x)
y_list = [y_1, y_2]
title_list = ['Cosine function', 'Logarithm function']
# 绘制多子图
plot_nums = 2
fig, axes = plt.subplots(1, plot_nums, sharey=True) # 获取Figure对象和Axes对象
fig.suptitle('Function curves')
for plot_id in range(plot_nums):
    ax = axes[plot_id] # 获取Axes对象
    ax.plot(y_list[plot_id])
    ax.set_title(title_list[plot_id])
fig.tight_layout() # 紧凑布局
plt.show()
plt.close()

设置子图共享y轴

参考

  1. plt.plot()函数解析(最清晰的解释)
  2. Figure、Axes对象是什么

文章作者: 鹿卿
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 鹿卿 !
评论
  目录