How is order of items in matplotlib legend determined?

后端 未结 5 766
迷失自我
迷失自我 2020-12-12 17:43

I am having to reorder items in a legend, when I don\'t think I should have to. I try:

from pylab import *
clf()
ax=gca()
ht=ax.add_patch(Rectangle((1,1),1,1,         


        
5条回答
  •  轮回少年
    2020-12-12 18:23

    The following function makes control of legend order easy and readable.

    You can specify the order you want by label. It will find the legend handles and labels, drop duplicate labels, and sort or partially sort them according to your given list (order). So you use it like this:

    reorderLegend(ax,['Top', 'Middle', 'Bottom'])
    

    Details are below.

    #  Returns tuple of handles, labels for axis ax, after reordering them to conform to the label order `order`, and if unique is True, after removing entries with duplicate labels.
    def reorderLegend(ax=None,order=None,unique=False):
        if ax is None: ax=plt.gca()
        handles, labels = ax.get_legend_handles_labels()
        labels, handles = zip(*sorted(zip(labels, handles), key=lambda t: t[0])) # sort both labels and handles by labels
        if order is not None: # Sort according to a given list (not necessarily complete)
            keys=dict(zip(order,range(len(order))))
            labels, handles = zip(*sorted(zip(labels, handles), key=lambda t,keys=keys: keys.get(t[0],np.inf)))
        if unique:  labels, handles= zip(*unique_everseen(zip(labels,handles), key = labels)) # Keep only the first of each handle
        ax.legend(handles, labels)
        return(handles, labels)
    
    
    def unique_everseen(seq, key=None):
        seen = set()
        seen_add = seen.add
        return [x for x,k in zip(seq,key) if not (k in seen or seen_add(k))]
     
    

    The function in updated form is in cpblUtilities.mathgraph at https://gitlab.com/cpbl/cpblUtilities/blob/master/mathgraph.py

    Usage is thus like this:

    fig, ax = plt.subplots(1)
    ax.add_patch(Rectangle((1,1),1,1,color='r',label='Top',alpha=.1))
    ax.bar(1,2,label='Middle')
    ax.add_patch(Rectangle((.8,.5),1,1,color='k',label='Bottom',alpha=.1))
    legend()
    
    
    reorderLegend(ax,['Top', 'Middle', 'Bottom'])
    show()
    

    The optional unique argument makes sure to drop duplicate plot objects which have the same label.

提交回复
热议问题