Matplotlib Legend:添加和自定义图例的完全指南
Updated on
没有图例的图表让读者猜测哪条线代表什么。他们在脑海中匹配颜色,误读数据,得出错误结论。使用plt.legend()添加图例很简单——但控制它出现的位置、外观,以及防止它遮挡数据,比大多数教程展示的要复杂得多。
本指南涵盖从基本图例创建到高级自定义的所有内容:图内和图外放置、多列布局、自定义句柄以及复杂图形的图例。
基本图例
自动标签
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend()
plt.show()plot()中的label参数定义了图例中显示的内容。调用plt.legend()来显示它。
面向对象风格
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend()
plt.show()图例放置
使用loc参数
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
# 常见位置
ax.legend(loc='upper right') # 默认
# ax.legend(loc='upper left')
# ax.legend(loc='lower right')
# ax.legend(loc='lower left')
# ax.legend(loc='center')
# ax.legend(loc='best') # 自动选择重叠最少的位置
plt.show()所有loc选项
| loc字符串 | loc数字 |
|---|---|
'best' | 0 |
'upper right' | 1 |
'upper left' | 2 |
'lower left' | 3 |
'lower right' | 4 |
'right' | 5 |
'center left' | 6 |
'center right' | 7 |
'lower center' | 8 |
'upper center' | 9 |
'center' | 10 |
使用bbox_to_anchor精确定位
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.plot(x, np.sin(x) + np.cos(x), label='sin(x) + cos(x)')
# 在轴比例坐标(x, y)处放置图例
ax.legend(loc='upper left', bbox_to_anchor=(0.02, 0.98))
plt.show()图例放在图外
当图例遮挡数据时,将其移到外部:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(6):
ax.plot(x, np.sin(x + i * 0.5), label=f'Phase {i}')
# 将图例放在图的右侧
ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
plt.tight_layout()
plt.show()import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 6))
for i in range(5):
ax.plot(x, np.sin(x + i), label=f'Series {i+1}')
# 将图例放在图的下方
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1), ncol=5)
plt.tight_layout()
plt.show()图例样式设置
字体大小和边框
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend(
fontsize=12,
frameon=True, # 显示边框(默认True)
framealpha=0.8, # 边框透明度
facecolor='lightyellow', # 背景颜色
edgecolor='gray', # 边框颜色
shadow=True, # 投影
)
plt.show()多列布局
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(8):
ax.plot(x, np.sin(x + i * 0.4), label=f'Signal {i+1}')
# 4列以实现紧凑的图例
ax.legend(ncol=4, loc='upper center', fontsize=9)
plt.show()图例标题
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, x**2, label='Quadratic')
ax.plot(x, x**1.5, label='Power 1.5')
ax.plot(x, x, label='Linear')
ax.legend(title='增长模型', title_fontsize=13, fontsize=11)
plt.show()自定义图例句柄
手动图例条目
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.lines as mlines
import numpy as np
fig, ax = plt.subplots(figsize=(8, 5))
# 不带标签绘图
ax.scatter(np.random.randn(50), np.random.randn(50), c='blue', s=20)
ax.scatter(np.random.randn(50) + 2, np.random.randn(50), c='red', s=20)
# 创建自定义句柄
blue_patch = mpatches.Patch(color='blue', label='组A')
red_patch = mpatches.Patch(color='red', label='组B')
line_handle = mlines.Line2D([], [], color='green', linestyle='--', label='阈值')
ax.legend(handles=[blue_patch, red_patch, line_handle])
plt.show()带颜色映射的散点图图例
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 5))
categories = ['A', 'B', 'C']
colors = ['#e74c3c', '#3498db', '#2ecc71']
for cat, color in zip(categories, colors):
x = np.random.randn(30)
y = np.random.randn(30)
ax.scatter(x, y, c=color, label=f'类别 {cat}', alpha=0.7, s=50)
ax.legend()
plt.show()图例自定义选项
| 参数 | 描述 | 示例 |
|---|---|---|
loc | 位置字符串或数字 | 'upper right', 2 |
bbox_to_anchor | 锚点 (x, y) | (1.0, 0.5) |
ncol | 列数 | 3 |
fontsize | 文字大小 | 12, 'small' |
title | 图例标题 | 'My Legend' |
frameon | 显示边框 | True, False |
framealpha | 边框透明度 | 0.8 |
facecolor | 背景颜色 | 'white' |
edgecolor | 边框颜色 | 'gray' |
shadow | 投影 | True |
markerscale | 标记大小倍数 | 1.5 |
labelspacing | 条目间垂直间距 | 0.5 |
handlelength | 图例线条长度 | 2.0 |
实用示例
多种图表类型的图例
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(5)
values = [23, 45, 56, 78, 32]
trend = [20, 35, 50, 65, 40]
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x, values, alpha=0.7, label='实际值', color='steelblue')
ax.plot(x, trend, 'ro-', label='趋势', linewidth=2)
ax.axhline(y=50, color='green', linestyle='--', label='目标')
ax.legend(loc='upper left')
ax.set_xlabel('季度')
ax.set_ylabel('收入 ($K)')
plt.show()双轴的独立图例
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(2020, 2027)
revenue = [100, 120, 115, 140, 160, 175, 200]
employees = [50, 55, 52, 60, 70, 75, 85]
fig, ax1 = plt.subplots(figsize=(8, 5))
line1 = ax1.plot(x, revenue, 'b-o', label='收入 ($M)')
ax1.set_ylabel('收入 ($M)', color='blue')
ax2 = ax1.twinx()
line2 = ax2.plot(x, employees, 'r-s', label='员工数')
ax2.set_ylabel('员工数', color='red')
# 合并图例
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='upper left')
plt.show()交互式数据探索
在反复调整图表美观和图例位置时,PyGWalker (opens in a new tab)让你可以在Jupyter中通过拖拽列来构建交互式可视化——图例、颜色和大小会自动生成:
import pandas as pd
import pygwalker as pyg
df = pd.read_csv('your_data.csv')
walker = pyg.walk(df)常见问题
如何在Matplotlib图表中添加图例?
在每个plot()、scatter()或bar()调用中添加label='name',然后调用plt.legend()或ax.legend()。图例会自动使用你提供的标签。
如何将图例移到图外?
使用bbox_to_anchor配合loc。放在右侧:ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))。放在下方:ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1))。调用plt.tight_layout()防止裁剪。
如何更改Matplotlib中的图例字体大小?
将fontsize传给legend():ax.legend(fontsize=14)或使用字符串大小如'small'、'medium'、'large'。对于标题:ax.legend(title='Title', title_fontsize=16)。
如何创建多列图例?
使用ncol参数:ax.legend(ncol=3)创建3列布局。当图例条目较多且需要紧凑的水平布局时,这很有用。
如何去除图例边框?
设置frameon=False:ax.legend(frameon=False)。要保留边框但使其透明,使用framealpha=0:ax.legend(framealpha=0)。
总结
Matplotlib图例从label参数和plt.legend()开始。使用loc进行标准定位,使用bbox_to_anchor将图例移到图外,使用ncol进行多列布局,使用fontsize、frameon和shadow等样式参数进行自定义。对于有多个系列的图表,将图例放在轴区域外并调用tight_layout()防止裁剪。对于具有双轴的复杂图形,手动组合线条句柄以创建统一的图例。