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,
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.