Подтвердить что ты не робот

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

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

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

Спасибо!


UPDATE:

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

4b9b3361

Ответ 1

Есть несколько способов сделать это. Самый простой способ - получить дескриптор для первой построенной строки каждой группы и передать это как первый аргумент 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'});

Ответ 2

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

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

Ответ 3

В ответ на ваше обновление и продление ответа 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

Дает следующий рисунок: Plot of Bessel functions with automatic legend

EDIT: в 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);

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

Ответ 4

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

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

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

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

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'));

Ответ 5

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

Ответ 6

Вам нужно будет скопировать lengends в массив, когда вы выполняете построение с помощью plot после ввода в режим hold all, который позволяет выполнять несколько графиков без переопределения друг друга. Затем, когда мы закончим, мы отключим его с помощью hold off.

Это небольшой код для быстрой справки. Он полностью отвечает на вопрос. Этот script делает все запрошенное, и все же это полностью рабочий пример:

% 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;

График вывода:

Литература: