Skip to content

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=Falseax.legend(frameon=False)。要保留边框但使其透明,使用framealpha=0ax.legend(framealpha=0)

总结

Matplotlib图例从label参数和plt.legend()开始。使用loc进行标准定位,使用bbox_to_anchor将图例移到图外,使用ncol进行多列布局,使用fontsizeframeonshadow等样式参数进行自定义。对于有多个系列的图表,将图例放在轴区域外并调用tight_layout()防止裁剪。对于具有双轴的复杂图形,手动组合线条句柄以创建统一的图例。

📚