legend for group of lines

后端 未结 6 405
盖世英雄少女心
盖世英雄少女心 2020-12-08 07:46

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

相关标签:
6条回答
  • 2020-12-08 08:27

    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
    0 讨论(0)
  • 2020-12-08 08:28

    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'});
    
    0 讨论(0)
  • 2020-12-08 08:30

    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)

    0 讨论(0)
  • 2020-12-08 08:35

    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'));
    
    0 讨论(0)
  • 2020-12-08 08:38

    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.

    0 讨论(0)
  • 2020-12-08 08:40

    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!

    0 讨论(0)
提交回复
热议问题