tags:

views:

87

answers:

3

Hi,

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.

+3  A: 

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'});
gnovice
THanks! 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.
Tim
@Tim: I don't know of any straightforward way to add labels to an existing legend. If you want to append a label, you will have to remake the whole legend.
gnovice
+3  A: 

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.

Andrew Janke
+2  A: 

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

related questions