Matplotlib自定义图例(多张图共享一个图例)
作者:MK422
最近再用Matplotlib绘图,需要做两个子图都不需要设置图例,图例单独用一个figure来显示,本文就详细的来介绍一下,感兴趣的可以了解一下
1、应用场景
可视化不同方法在各种超参数(或者不同数据集)的性能时,若用多个子图形式可视化,则图太小啦;若每个子图弄成单独的figure,则每个张图都有一个图例显得非常冗余,如图1所示。

图1 每张图都有一个图例(非常冗余,并且有的数据被遮挡)
2、期望达到的效果,如图2所示
解决方案:两个子图都不需要设置图例,图例单独用一个figure来显示(自定义图例)

图2 期望的效果
3、自定义图例matplotlib代码实现
方法一:利用Patch以及Line2D自定义图例
- 缺点:暂时只能定义直线的图的图例;散点图的图例不行;
- 优点:运行该代码后,Figure 1就是我们想要的图例图。
import matplotlib.pyplot as plt
import matplotlib.lines as lines
import matplotlib.patches as mpatches
# 自定义图例标记
line1 = lines.Line2D([0], [0], label='line1', marker='o', lw=2, c='green')
line2 = lines.Line2D([0], [0], label='line2', marker='X', lw=2, c='blue')
patch1 = mpatches.Patch(color='purple', label='patch1')
patch2 = mpatches.Patch(color='red', label='patch2')
# 构造图例
# plt.figure() figsize: default: [6.4, 4.8]
handles = [line1, line2, patch1, patch2]
# 注意根据图例的行数调整figsize的高度(i.e., 0.32)
fig, ax = plt.subplots(figsize=(6.4, 0.32))
ax.legend(handles=handles, mode='expand', ncol=4, borderaxespad=0)
"""
legend常见参数设置
borderpad:控制上下边距(default=0.4)
borderaxespad:控制legend与图边框的距离(default=0.5)
handlelength: handle与legend边框的距离(default=2)
handletextpad: handle与text之间的距离(default=0.8)
mode='expand', 水平展示图例
frameon=False: 不要图例边框
edgecolor: 图例边框颜色
fontsize: 图例字体大小
ncol=4 水平图例的个数
"""
ax.axis('off') # 去掉坐标的刻度
plt.show()方法一可视化效果,如图3所示

图3 方法一可视化效果
方法二:利用plt自定义图例
- 缺点:会显示2个Figure,其中Figure 2才是我们想要的图例图;
- 优点:和我们以前画图的方式一样(更加简单),并且能够构建散点图的图例;
import matplotlib.pyplot as plt
# plt.plot()返回值后面要加一个逗号,不然会报错;若使用Line2D就不需要逗号
# 注意:range(10)是随机取的值,这里只需要它的图例图。
l1, = plt.plot(range(10), label='line1', marker='o', lw=2, c='green')
l2, = plt.plot(range(10), label='line2', marker='X', lw=2, c='blue')
s1 = plt.scatter(range(10), range(10), label='scatter1', marker='+')
s2 = plt.scatter(range(10), range(10), label='scatter2', marker='+')
fig, ax = plt.subplots(figsize=(6.4, 0.32))
ax.legend(handles=[l1, l2, s1, s2], labels=list('abcd'), mode='expand', ncol=4, borderaxespad=0)
# ax.legend(handles=[l1, s1], labels=list('ab'), mode='expand', ncol=4, borderaxespad=0) # 若只需要显示部分曲线/散点图的图例时
ax.axis('off') # 去掉坐标的刻度
plt.show()方法二可视化效果,如图4所示

图4 方法三的可视化效果,其中Figure 2就是我们需要的图
方法三:混合实验方法一和方法二
import matplotlib.pyplot as plt
import matplotlib.lines as lines
import matplotlib.patches as mpatches
# 自定义图例标记
line1 = lines.Line2D([0], [0], label='line1', marker='o', lw=2, c='green')
# 注意line2后面的逗号
line2, = plt.plot([0], [0], label='line2', marker='X', lw=2, c='blue')
s = plt.scatter([0], [0], label='scatter', marker='+')
patch1 = mpatches.Patch(color='purple', label='patch1')
# patch2 = mpatches.Patch(color='red', label='patch2')
# 构造图例
# plt.figure() figsize: default: [6.4, 4.8]
handles = [line1, line2, patch1, s]
# 注意根据图例的行数调整figsize的宽(i.e., 0.32)
fig, ax = plt.subplots(figsize=(6.4, 0.32))
ax.legend(handles=handles, mode='expand', ncol=4, borderaxespad=0)
"""
legend常见参数设置
axes:图框; handle:图例的每个元素; text:图例每个元素对应name
borderpad:控制上下边距(default=0.4)
borderaxespad:控制legend与图边框的距离(default=0.5)
handlelength: handle与legend边框的距离(default=2)
handletextpad: handle与text之间的距离(default=0.8)
mode='expand', 水平展示图例
frameon=False: 不要图例边框
edgecolor: 图例边框颜色
fontsize: 图例字体大小
ncol=4 水平图例的个数
"""
# plt.scatter
ax.axis('off') # 去掉坐标的刻度
plt.show()方法三的可视化效果如图5所示

图5 方法三可视化修改,其中Figure 2就是我们需要的图例图
4、总结
# 导入对应的模块 from matplotlib import lines import matplotlib.pyplot as plt from matplotlib import patches a. 定义线图例 # 方法1 line1 = lines.Line2D([0], [0], label='line1', marker='o', lw=2, c='green') # 方法2,注意别丢逗号 line2, = plt.plot([0], [0], label='line2', marker='X', lw=2, c='blue') b. 定义矩形图例 path1 = mpatches.Patch(color='red', label='patch') c. 定义散点图图例 s1 = plt.scatter([0], [0], label='scatter', marker='+') d. 显示图例 handles = [line1, path1, line2, s1] fig, ax = plt.subplots(figsize=(6.4, 0.32)) # 根据行数更改0.32 ax.legend(handles=handles, mode='expand', ncol=4, borderaxespad=0) ax.axis(“off”) # 去掉坐标刻度
5、用visio将单张的图片合并在一起,并且手动构建图例,图例的样式更人性化。
到此这篇关于Matplotlib自定义图例(多张图共享一个图例)的文章就介绍到这了,更多相关Matplotlib自定义图例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
