pythonmatplotlibplotlegend

Matplotlib: Multiple legends on same figure


I have a few plot functions that each receive different kinds of data and plot them, with their own title and legends. However, when I try to plot them on the same figure, the former one is overwritten.

I understand that one way to do this is to call get_artist(), however since the legends are created inside functions, this doesn't seem possible. Is there any type of LegendHandler to do this? To retrieve the legend from each plot and show them on the figure? Should I return the legend from each function?

Here is a simplified code of what I have:

def plot_1(fig, data, ax = None):
    if ax = None:
        ax = fig.add_subplot(111)
    ax.plot(data)
    ax.set_xlabel('t')
    plt.axis('tight')

    # Create a legend
    colors = {'A':'blue',
              'B':'yellow',
              'C':'red'}
    legend_labels = []
    legend_handles = []

    for key in colors.keys():
        legend_labels.append(key)
        p = matplotlib.patches.Rectangle((0, 0), 1, 1, fc = colors[key], alpha = 0.5)
        legend_handles.append(p)
    ax.legend(legend_handles, legend_labels, loc='center left', bbox_to_anchor=(1, 0.5))

def plot_2(fig, data, ax = None):
    if ax = None:
        ax = fig.add_subplot(111)
    ax.plot(data, color='green', linewidth=1, label='L1')
    ax.set_xlabel('t')
    ax.autoscale()
    ax.legend()

def main():

    plot_1(fig, data = data1)
    plot_2(fig, data = data2)

I'm not sure if this is the best way to do it, but since I am using these plotting models multiple times, I feel that I have to keep them in function forms as they are.

Note from comment:


Solution

  • I have actually solved it using that [add_artist] for now, but I was looking for a cleaner way

    There is no cleaner way.

    Each Axes object (each subplot) maintains a .legend_ attribute, that is initially set to None and later is destructively updated each time ax.legend(...) or plt.legend(...) is used.

    Your only choice is to label (give a name to) the first legend Artist, and when it's removed from the Axes namespace. i.e,, from ax.legend_ you MUST place it into the Axes again, using ax.add_artist(...).

    Re WHY Matplotlib is designed like this, I'd ask MATLAB designers but I may be wrong :-)