легенда для группы линий

Мне нравится отображать две группы линий на одном графике. В каждой группе есть две линии одного цвета, и я должен рисовать их в порядке одной группы за другой группой. Я стараюсь показывать легенду только для групп, а не для строк. Как я могу это сделать? Вот упрощение моего неправильного кода:

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})

Спасибо!


ОБНОВИТЬ:

Новый вопрос, есть ли способ написать легенду после каждой строки и не перезаписывать предыдущую легенду, а добавлять к ней? то есть что-то похожее на «держись», но применительно к легенде.


person Tim    schedule 26.01.2010    source источник


Ответы (6)


Есть несколько способов сделать это. Самый простой способ — получить дескриптор первой линии графика каждой группы и передать его в качестве первого аргумента в ЛЕГЕНДА:

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'});
person gnovice    schedule 26.01.2010
comment
Спасибо! Новый вопрос, есть ли способ написать легенду после каждой строки и не перезаписывать предыдущую легенду, а добавлять к ней? то есть что-то похожее на держись, но применительно к легенде. - person Tim; 26.01.2010
comment
@Tim: я не знаю простого способа добавить метки к существующей легенде. Если вы хотите добавить метку, вам придется переделать всю легенду. - person gnovice; 26.01.2010

Вы можете сшить несколько строк вместе, используя 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');

Это также может позволить вам установить свойства set() для сгруппированных строк как единиц.

person Andrew Janke    schedule 26.01.2010

В ответ на ваше обновление и в дополнение к ответу Эндрю Янке я обнаружил, что этот метод идеально подходит для автоматической легенды:

% 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 использование «легенды» изменилось, и приведенные выше решения будут вызывать ошибки. Вместо этого мы должны изменить свойство 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);

Теперь вы можете добавить столько графиков, сколько захотите, и легенда будет автоматически обновляться!

person PhD_Dan    schedule 18.04.2013

Re: ваше обновление:

Чтобы обновить легенду, вам нужно заменить все это, снова вызвав «легенду (имена)». Вы можете использовать четвертый аргумент геттерной формы legend(), чтобы определить текущие имена, а затем просто добавить свои. (Это предполагает, что все линии на графике были добавлены с помощью чего-то, что постепенно обновляет легенду таким образом.)

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

Другой способ — отслеживать имена линий с помощью их свойства DisplayName, а затем перестраивать легенду на основе текущего состояния графика при добавлении чего-то нового. DisplayName — это то, что легенда() использует для автоматического создания имен строк, когда вы вызываете простую форму «показ легенды». ИМХО, это немного лучше, поскольку легенда действует как представление о текущем состоянии графика, а не требует от вызывающих абонентов синхронизировать их.

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'));
person Andrew Janke    schedule 27.01.2010

На самом деле, это можно сделать без взлома, используя 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)

person Kaare    schedule 12.03.2013

Вам нужно будет накапливать lengends в массиве, поскольку вы выполняете построение с помощью plot после того, как мы войдем в режим hold all, который позволяет выполнять несколько графиков без переопределения друг друга. Затем, когда мы закончим, мы отключим его с помощью 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
person user    schedule 05.12.2016