Search code examples
pythonmatplotlibplot

How to get all legends from a plot?


I have a Plot with 2 or more legends. How can I "get" all the legends to change (for example) the color and linestyle in the legend?

handles, labels = ax.get_legend_handles_labels() only gives me the "first" legend, which I added to the plot with plt.legend(). But I want the others legends too, which I added with plt.gca().add_artist(leg2) How can I do that?


Solution

  • You can get all children from an axes and filter on the legend type with:

    legends = [c for c in ax.get_children() if isinstance(c, mpl.legend.Legend)]
    

    But does that work at all? If i add more legends like you mention, i see multiple Legend children, but all are pointing to the same object.

    edit:

    The axes itself keeps the last legend added, so if you add the previous with .add_artist(), you see multiple different legends:

    For example:

    fig, ax = plt.subplots()
    
    l1, = ax.plot(x,y, 'k', label='l1')
    leg1 = plt.legend([l1],['l1'])
    
    l2, = ax.plot(x,y, 'k', label='l2')
    leg2 = plt.legend([l2],['l2'])
    
    ax.add_artist(leg1)
    
    print(ax.get_children())
    

    Returns these objects:

    [<matplotlib.axis.XAxis at 0xd0e6eb8>,
     <matplotlib.axis.YAxis at 0xd0ff7b8>,
     <matplotlib.lines.Line2D at 0xd0f73c8>,
     <matplotlib.lines.Line2D at 0xd5c1a58>,
     <matplotlib.legend.Legend at 0xd5c1860>,
     <matplotlib.legend.Legend at 0xd5c4b70>,
     <matplotlib.text.Text at 0xd5b1dd8>,
     <matplotlib.text.Text at 0xd5b1e10>,
     <matplotlib.text.Text at 0xd5b1e48>,
     <matplotlib.patches.Rectangle at 0xd5b1e80>,
     <matplotlib.spines.Spine at 0xd0e6da0>,
     <matplotlib.spines.Spine at 0xd0e6ba8>,
     <matplotlib.spines.Spine at 0xd0e6208>,
     <matplotlib.spines.Spine at 0xd0f10f0>]
    

    It remains to be seen whether this is something you want to do!? You can also store the lines (or other types) yourself separately from the axes.