线组的图例

发布于 2024-08-19 14:08:57 字数 366 浏览 3 评论 0原文

我喜欢在同一个图中绘制两组线。每组有两条相同颜色的线,我必须按照一组又一组的顺序绘制它们。我尝试仅显示组的图例而不是行的图例。我该怎么做?这是我的错误代码的简化:

plot(x1, y1, color1); hold on;
plot(x2, y2, color1); hold on;

plot(x3, y3, color2); hold on;
plot(x4, y4, color2); hold on;

legend({color1, color2})

谢谢!


更新:

一个新问题,有没有什么方法可以在每行之后编写图例,而不覆盖前一个图例,而是附加到它后面?即类似于“坚持”但适用于图例的东西。

I like to plot two groups of lines in the same plot. Each group has two lines with same color and I have to draw them in the order of one group after another group. I try to show legend for groups only not for lines. How can I do this? Here is a simplification of my wrong code:

plot(x1, y1, color1); hold on;
plot(x2, y2, color1); hold on;

plot(x3, y3, color2); hold on;
plot(x4, y4, color2); hold on;

legend({color1, color2})

Thanks!


UPDATE:

A new question, is there any way to write legend after each line and without overwriting the previous legend but append to it? i.e. something similar to "hold on" but applied to legend.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

迷离° 2024-08-26 14:08:57

有几种方法可以做到这一点。最简单的方法是获取每组第一条绘制线的句柄,并将其作为第一个参数传递给 图例

h1 = plot(x1, y1, color1);
hold on;
plot(x2, y2, color1);

h2 = plot(x3, y3, color2);
plot(x4, y4, color2);

legend([h1 h2],{'label1', 'label2'});

There are a few ways you can do this. The easiest way is to get the handle for the first plotted line of each group and pass that as the first argument to LEGEND:

h1 = plot(x1, y1, color1);
hold on;
plot(x2, y2, color1);

h2 = plot(x3, y3, color2);
plot(x4, y4, color2);

legend([h1 h2],{'label1', 'label2'});
a√萤火虫的光℡ 2024-08-26 14:08:57

您可以使用 NaN 将多条线缝合在一起,NaN 的意思是“拿起笔”。然后图例会将每个数据视为一组数据。

hold on
plot([x1 NaN x2], [y1 NaN y2], 'b');
plot([x3 NaN x4], [y3 NaN y4], 'r');
legend({'foo', 'bar'})
hold off

为了方便起见,您可以将其粘贴到绘图的多行版本中。

plot([x1 NaN x2], [y1 NaN y2], 'b', [x3 NaN x4], [y3 NaN y4], 'r');

这也可以让您将分组的行的属性设置为单位。

You can stitch multiple lines together using NaN, which means "pick up the pen". Then the legend will treat each as a single set of data.

hold on
plot([x1 NaN x2], [y1 NaN y2], 'b');
plot([x3 NaN x4], [y3 NaN y4], 'r');
legend({'foo', 'bar'})
hold off

For convenience, you can stick this in the multi-line version of plot.

plot([x1 NaN x2], [y1 NaN y2], 'b', [x3 NaN x4], [y3 NaN y4], 'r');

This could let you set() properties for the grouped lines as units, too.

埖埖迣鎅 2024-08-26 14:08:57

为了响应您的更新,并扩展 Andrew Janke 的答案,我发现这种方法非常适合自动图例:

% Sample data
order = -1:2;      % number of orders to plot
x = (0:0.01:10)';

% Plot each instance of data in a separate graph
for i=1:numel(order)
    plot(x,besselj(order(i),x))
    hold all

    % Amend legend to include new plot
    [~,~,~,current_entries] = legend;
    legend([current_entries {sprintf('Order = %i',order(i))}]);
end

给出下图:
带有自动图例的贝塞尔函数图

编辑:在 Matlab 2014b 中,“图例”的使用已更改,解决方案(s )上面会抛出错误。相反,我们应该修改图例的“String”属性。按照此代码可以获得与我之前的示例相同的结果:

% Sample data
order = -1:2;      % number of orders to plot
x = (0:0.01:10)';

% Plot each instance of data in a separate graph
for i=1:numel(order)
    plot(x,besselj(order(i),x))
    hold on

    % Amend legend 'entries' to include new plot
    entries(i) = { sprintf('Order = %i',order(i)) };
end

% Create legend using the 'entries' strings
legend('String',entries);

现在您可以添加任意数量的绘图,图例将自动更新!

In response to your update, and to extend Andrew Janke's answer, I found this method to be perfect for an automatic legend:

% Sample data
order = -1:2;      % number of orders to plot
x = (0:0.01:10)';

% Plot each instance of data in a separate graph
for i=1:numel(order)
    plot(x,besselj(order(i),x))
    hold all

    % Amend legend to include new plot
    [~,~,~,current_entries] = legend;
    legend([current_entries {sprintf('Order = %i',order(i))}]);
end

Gives the following figure:
Plot of Bessel functions with automatic legend

EDIT: In Matlab 2014b, the use of "legend" has changed and the solution(s) above will throw errors. Instead, we should modify the 'String' property of the legend. Follow this code to get the same result as my previous example:

% Sample data
order = -1:2;      % number of orders to plot
x = (0:0.01:10)';

% Plot each instance of data in a separate graph
for i=1:numel(order)
    plot(x,besselj(order(i),x))
    hold on

    % Amend legend 'entries' to include new plot
    entries(i) = { sprintf('Order = %i',order(i)) };
end

% Create legend using the 'entries' strings
legend('String',entries);

Now you can add as many plots as you want and the legend will automatically update!

多情癖 2024-08-26 14:08:57

回复:您的更新:

要更新图例,您需要再次调用“图例(名称)”来替换整个内容。您可以使用 legend() 的 getter 形式的第四个参数来确定当前名称,然后附加您的名称。 (这假设图中的所有线条都已使用以这种方式增量更新图例的内容添加。)

[~,~,~,names] = legend;
legend([names {'my new line name'}]);

另一种方法是使用其 DisplayName 属性跟踪线条的名称,然后根据当前状态重建图例。添加新内容时的情节。 DisplayName 是 legend() 在调用简单的“图例显示”表单时用来自动生成行名称的名称。恕我直言,这更好一点,因为图例充当当前绘图状态的视图,而不是要求调用者保持两者同步。

function repro_incremental_legend
%REPRO_INCREMENTAL_LEGEND Demonstrate plots with incrementally updated legend
figure; hold on
x = 1:5;
names = {'foo', 'bar', 'baz', 'qux'};
for i = 1:4
    myplot(gca, x, x.*(1/i), names{i});
    update_legend(gca);
    pause(1); % remove in real code
end

function myplot(ax, x, y, name)
%MYPLOT Wrapper for plot() that respects ColorOrder and sets DisplayName
h = plot(ax, x, y); % plot before setting color so HOLD state is respected
set(h, 'DisplayName', name);
ColorOrder = get(ax, 'ColorOrder');
nLines = numel(get(ax, 'Children'));
set(h, 'Color', ColorOrder(1+mod(nLines-1, size(ColorOrder,1)),:));

function update_legend(ax)
%UPDATE_LEGEND Update legend based on current child lines
kids = get(ax, 'Children');
kids = kids(end:-1:1); % Legend seems to have the opposite ordering
legend(get(kids, 'DisplayName'));

Re: your update:

To update a legend, you need to replace the whole thing by calling "legend(names)" again. You can use the fourth argument of the getter form of legend() to determine the current names, and then just append yours. (This assumes that all of the lines in the plot have been added using something that incrementally updates the legend this way.)

[~,~,~,names] = legend;
legend([names {'my new line name'}]);

Another way is to track the names of lines using their DisplayName property, and then rebuild the legend based on the current state of the plot when you add something new. DisplayName is what legend() uses to auto-generate the line names when you call the simple "legend show" form. IMHO this is a bit nicer in that legend acts as a view on the current plot state, rather than requiring the callers to keep the two in sync.

function repro_incremental_legend
%REPRO_INCREMENTAL_LEGEND Demonstrate plots with incrementally updated legend
figure; hold on
x = 1:5;
names = {'foo', 'bar', 'baz', 'qux'};
for i = 1:4
    myplot(gca, x, x.*(1/i), names{i});
    update_legend(gca);
    pause(1); % remove in real code
end

function myplot(ax, x, y, name)
%MYPLOT Wrapper for plot() that respects ColorOrder and sets DisplayName
h = plot(ax, x, y); % plot before setting color so HOLD state is respected
set(h, 'DisplayName', name);
ColorOrder = get(ax, 'ColorOrder');
nLines = numel(get(ax, 'Children'));
set(h, 'Color', ColorOrder(1+mod(nLines-1, size(ColorOrder,1)),:));

function update_legend(ax)
%UPDATE_LEGEND Update legend based on current child lines
kids = get(ax, 'Children');
kids = kids(end:-1:1); % Legend seems to have the opposite ordering
legend(get(kids, 'DisplayName'));
紫轩蝶泪 2024-08-26 14:08:57

实际上,有一种非黑客方法可以做到这一点,即使用 hggroups。下面绘制了几行,但图例将它们视为只有两条:(

t = 0:.1:2*pi;
for k=1:5
    offset = k/7;
    m(:,k) = t+offset';
end
hSLines = plot(t,sin(m),'Color','b');hold on
hCLines = plot(t,cos(m),'Color','g');
hSGroup = hggroup;
hCGroup = hggroup;
set(hSLines,'Parent',hSGroup)
set(hCLines,'Parent',hCGroup)
% Include these hggroups in the legend:
set(get(get(hSGroup,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); 
set(get(get(hCGroup,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); 
legend('Sine','Cosine')

无耻地从 http://www.mathworks.se/help/matlab/creating_plots/controlling-legends.html

Actually, there is a non-hack way to do this, using hggroups. The below plots several lines, but the legend treats them as just two:

t = 0:.1:2*pi;
for k=1:5
    offset = k/7;
    m(:,k) = t+offset';
end
hSLines = plot(t,sin(m),'Color','b');hold on
hCLines = plot(t,cos(m),'Color','g');
hSGroup = hggroup;
hCGroup = hggroup;
set(hSLines,'Parent',hSGroup)
set(hCLines,'Parent',hCGroup)
% Include these hggroups in the legend:
set(get(get(hSGroup,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); 
set(get(get(hCGroup,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); 
legend('Sine','Cosine')

(shamelessly copied from http://www.mathworks.se/help/matlab/creating_plots/controlling-legends.html)

会傲 2024-08-26 14:08:57

当我们进入 hold all 模式后使用 plot 执行绘图时,您将需要在数组上累积 lengends,这允许几个要执行的图不会相互覆盖。然后,一旦完成,我们就用 hold off 禁用它。

这是供快速参考的较小代码。它完全回答了问题。该脚本执行了所有请求的操作,但它是一个完全有效的示例:

% To clean stuff.
clc
clear
close all

% Set some nice settings.
grid on;
format long;

% Hold the graphics output until we are good to go.
hold all;

% To create some random test data.
x1 = 0 : 0.1 : 1;
y1 = sin( x1 );
y2 = cos( x1 );
y3 = tan( x1 );

% To perform the plotting. Here to start answering the question.
plot(x1,y1,'--g','LineWidth',2);
legendText(end+1) = { 'Sin(x)' };

plot(x1,y2,'--b','LineWidth',2);
legendText(end+1) = { 'Cos(x)' };

plot(x1,y3,'-k','LineWidth',2);
legendText(end+1) = { 'Tan(x)' };

% Add the legends to the plotting.
legend(legendText,'location','northwest');

% Flush/display our accumulated plotting until now.
hold off;

输出图形:

参考文献:

  1. https://www.mathworks.com/help/matlab/creating_plots/add-plot-to-existing-graph.html

You will need to accumulate the lengends on a array, as you perform the plotting with plot after we enter on the hold all mode, which allow several plots to be performed without overriding each other. Then once we are finish, we disable it with hold off.

This is smaller code for quick reference. It completely answer the question. This script does everything requested, and yet, it is a completely working example:

% To clean stuff.
clc
clear
close all

% Set some nice settings.
grid on;
format long;

% Hold the graphics output until we are good to go.
hold all;

% To create some random test data.
x1 = 0 : 0.1 : 1;
y1 = sin( x1 );
y2 = cos( x1 );
y3 = tan( x1 );

% To perform the plotting. Here to start answering the question.
plot(x1,y1,'--g','LineWidth',2);
legendText(end+1) = { 'Sin(x)' };

plot(x1,y2,'--b','LineWidth',2);
legendText(end+1) = { 'Cos(x)' };

plot(x1,y3,'-k','LineWidth',2);
legendText(end+1) = { 'Tan(x)' };

% Add the legends to the plotting.
legend(legendText,'location','northwest');

% Flush/display our accumulated plotting until now.
hold off;

Output Graphic:

References:

  1. https://www.mathworks.com/help/matlab/creating_plots/add-plot-to-existing-graph.html
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文