Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 557
Hubschr Avatar asked Jun 10 '14 11:06

Hubschr


2 Answers

Solution

An alternative: ax.get_legend()

legends = ax.get_legends()

To access the properties of the legends:

legends = ax.get_legend()
dict_legends = {'Legends': dict()}
if not isinstance(legends, list):
    legends = [legends]
for i, legend in enumerate(legends):     
    dict_legend = dict()                                                           
    for j, obj in enumerate(lgnd.get_texts()):
        dict_obj = dict()
        dict_fp = dict()
        text = obj.get_text()
        position = obj.get_position()
        color = obj.get_color()    
        dict_obj.update({'Text': text, 
                         'Position': tuple(position), 
                         'Color': color})
        obj_fp = obj.get_font_properties()
        dict_fp.update({'Font_Name': obj_fp.get_name()})
        fontconfig_pattern = obj_fp.get_fontconfig_pattern()
        font_properties = str.split(fontconfig_pattern,":")
        for fp in font_properties:
            if not (fp.strip()==''):
                key, value = fp.split("=")
                dict_fp.update({str.title(key): value})        
        dict_fp.update({'fontconfig_pattern': fontconfig_pattern})
        dict_obj.update({'Font_Properties': dict_fp})    
        dict_legend.update({'Text_Object_{}'.format(j+1): dict_obj})    
    dict_legends['Legends'].update({'Legend_{}'.format(i): {'Legend_Object': legend, 
                                                            'Contents': dict_legend}})

print(dict_legends)

Configuration:

#  Windows: 10  
#  Python: 3.6  
#  Matplotlib: 2.2.2  
like image 61
CypherX Avatar answered Sep 20 '22 06:09

CypherX


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.

like image 36
Rutger Kassies Avatar answered Sep 22 '22 06:09

Rutger Kassies