Skip to content

MATLAB - 为坐标轴添加图例

MATLAB - 为绘图创建信息丰富的图例

Section titled “MATLAB - 为绘图创建信息丰富的图例”

图例(legend)是任何科学或数据驱动绘图的关键组成部分。它充当一个关键,解释可视化中每种线条样式、标记或颜色所代表的含义。没有图例的绘图可能模糊不清或具有误导性。MATLAB 提供了灵活的 legend 函数来创建清晰且具有描述性的图例。

创建图例的现代且最健壮(robust)的方法是在创建每个绘图对象时为其分配一个 DisplayName(显示名称)。这会将绘图代码与图例创建解耦,从而使代码更清晰、更易于维护。

% 现代推荐方法
plot(x1, y1, 'DisplayName', 'Data Series 1')
hold on
plot(x2, y2, 'DisplayName', 'Data Series 2')
hold off
legend
% 传统/手动方法
legend('Label 1', 'Label 2', ..., 'Label N')
% 高级自定义
legend(..., 'Name', Value) % 例如,'Location', 'northwest'
  • plot(..., 'DisplayName', name):这个在绘图函数(如 plot、scatter、bar 等)中的名称-值对将一个标签分配给特定的图形对象。这是首选的最佳实践。
  • legend:当不带任何参数调用时,legend 会自动查找所有设置了 DisplayName 属性的绘图对象,并从中创建图例。它会智能地忽略没有 DisplayName 的绘图。
  • legend('Label1', 'Label2', ...):这会根据绘图创建的顺序手动为绘图分配标签。这种方法可能很脆弱;如果改变绘图顺序,你也必须改变图例顺序。
  • legend(..., 'Name', Value):自定义图例的属性。最常见的是 'Location' 用来控制其位置,但你也可以改变字体大小、方向等。

让我们绘制 sin(x) 和 cos(x) 并使用 DisplayName 属性来创建健壮的图例。

% 1. 创建数据
x = linspace(0, 2*pi, 100);
% 2. 创建图形和坐标轴
figure;
ax = gca; % 获取当前坐标轴句柄
% 3. 绘制数据,为每个绘图分配 DisplayName
plot(ax, x, sin(x), 'b-', 'LineWidth', 2, 'DisplayName', 'sin(x)');
hold on; % 保持当前绘图活跃
plot(ax, x, cos(x), 'r--', 'LineWidth', 2, 'DisplayName', 'cos(x)');
hold off; % 释放绘图
% 4. 添加标题和标签以提供上下文
title(ax, 'Sine and Cosine Functions');
xlabel(ax, 'Angle [rad]');
ylabel(ax, 'Value');
grid on;
% 5. 自动创建图例
legend;

优点:如果你决定添加另一个绘图,比如 tan(x),你只需添加另一个带有其自己 DisplayName 的 plot 命令即可。legend 命令根本不需要改变。

有时默认的图例位置会遮盖重要数据。你可以轻松移动它。

x = linspace(0, 10, 100);
y1 = exp(-0.2*x) .* sin(x);
y2 = exp(-0.1*x) .* cos(x);
figure;
plot(x, y1, 'DisplayName', 'Damped Sine');
hold on;
plot(x, y2, 'DisplayName', 'Damped Cosine');
hold off;
title('Damped Oscillations');
xlabel('Time [s]');
ylabel('Amplitude');
grid on;
% 创建图例并指定属性
lgd = legend('Location', 'northeast', 'FontSize', 12);
title(lgd, 'Signals'); % 为图例本身添加标题!

专业提示:常用的 'Location' 值包括 'best'、'northwest'、'southwest'、'northeast'、'southeast' 和 'center'。使用 'best' 可以让 MATLAB 尝试找到数据重叠最少的位置。

如果你有一些辅助绘图(如趋势线)不想包含在图例中怎么办?DisplayName 方法会自动处理此情况。或者,你也可以手动指定要包含哪些绘图。

x = linspace(0, pi, 50);
y1 = cos(x);
p1 = plot(x, y1, 'DisplayName', 'cos(x)'); % 带 DisplayName 的绘图
hold on
y2 = 0.5*cos(2*x);
plot(x, y2); % 不带 DisplayName 的绘图
y3 = 0.25*cos(3*x);
p3 = plot(x, y3, 'DisplayName', '0.25*cos(3x)'); % 带 DisplayName 的绘图
hold off
title('Including only relevant data in legend');
% 方法 1:自动(推荐)
% 简单地调用 legend 将只包含 p1 和 p3
legend('Location', 'southwest');
% --- 或 ---
% 方法 2:手动控制(如果需要覆盖)
% legend([p1, p3]); % 通过传递句柄实现相同结果

在此示例中,第二个 0.5*cos(2*x) 的绘图被视为视觉辅助,并因缺少 DisplayName 而被正确地排除在图例之外。

  • 警告:忽略额外的图例条目:如果你使用手动方法 legend('A', 'B', 'C') 但坐标轴上只有两个绘图时,就会发生这种情况。请确保标签的数量与绘制系列的数量匹配。
  • 图例为空:当没有绘图设置 DisplayName 时调用 legend 可能会发生这种情况。请仔细检查你是否已将 'DisplayName' 属性添加到你的绘图命令中。
  • 程序化控制:对于高度动态的绘图,你可以通过设置其 HandleVisibility 属性来程序化地关闭某个项目在图例中的包含:p.HandleVisibility = 'off';。这是用于复杂 GUI 或应用程序的高级技术。