Search code examples
sortingmatplotlibziplegend

Sort a zipped list (string,instances of 'Line2D') by the last character of the string


I would like to sort the list of labels, handles that I obtained from the legend in Matplotlib after the last character of the string in labels.

So far I tried to combine this thread: How is order of items in matplotlib legend determined? with this thread: How to sort a list by last character of string which unfortunately did not work. Here is my Code:

handles, labels = ax.get_legend_handles_labels()

handles, labels = zip(*sorted(zip(labels, handles), key = lambda t:[0]))

leg = ax.legend(handles, labels,loc='best', ncol=2, shadow=True, fancybox=True)

Which basically does nothing.

Here are the printouts:

print(handles)
print(labels)

[<matplotlib.lines.Line2D object at 0x7fd6182ddcd0>, <matplotlib.lines.Line2D object at 0x7fd6182ddb50>, <matplotlib.lines.Line2D object at 0x7fd6448ddc10>, <matplotlib.lines.Line2D object at 0x7fd6448ddf50>, <matplotlib.lines.Line2D object at 0x7fd6609cb790>, <matplotlib.lines.Line2D object at 0x7fd6609cb190>, <matplotlib.lines.Line2D object at 0x7fd660ac5f10>, <matplotlib.lines.Line2D object at 0x7fd660ac5e90>, <matplotlib.lines.Line2D object at 0x7fd619404d10>, <matplotlib.lines.Line2D object at 0x7fd645fcb9d0>]
['Demo_4 maximum', 'Demo_4 mean', 'Demo_5 maximum', 'Demo_5 mean', 'Demo_6 maximum', 'Demo_6 mean', 'Demo_7 maximum', 'Demo_7 mean', 'Demo_8 maximum', 'Demo_8 mean']

Solution

  • You are almost there. There are a few corrections to be made to the line

    handles, labels = zip(*sorted(zip(labels, handles), key = lambda t:[0]))
    
    1. If you expect to receive handles, labels,, then you have to zip in the same order: zip(handles, labels)

    2. The key to sort by the first list would be lambda t: t[0] (notice the t). But because we now have handles first, and labels second, to sort by labels, it would be lambda t: t[1] (1 is the second list, in this case, labels)

    3. But you do not want to sort by labels, but by the last character of labels. You get the last character of a string s by s[-1]. So, the key should be lambda t: t[1][-1] (the [1] because labels is in the second position; the [-1] because you want the last character of each label).

    So:

    handles, labels = zip(*sorted(zip(handles, labels), key = lambda t: t[1][-1]))