Matplotlib's legend: how to order entries by row first, rather than by column

Question:

By default Matplotlib orders the entries in the legend by column, e.g.,

In [48]: from matplotlib.pyplot import subplots, show
    ...: f, ax = subplots(figsize=(6, 2), constrained_layout=True)
    ...: for i in range(1, 10):
    ...:     ax.plot((0,1),(0,1), label=str(i))
    ...: ax.legend(ncol=4, loc=3)
    ...: show()

enter image description here

but I’d like better to have the entries listed by rows, like

1  2  3  4
5  6  7  8
9

I could reorder the handles and labels and invoke ax.legend passing the reordered lists (I’ll post that as an answer if requested in comments) but I’d like to know if there is a more direct and straightforward way to instruct Matplotlib to do as I want, so that I don’t have to copy and paste the reorder solution in 50% of the Matplotlib scripts I’ll write…

Asked By: gboffi

||

Answers:

You can get the lists of handles to artists and the labels using the Axes method get_legend_handles_labels, then you call legend passing the reordered lists.

To reorder the lists, we observe that

  • legend places in the first column the first elements in the lists, then proceeds with the following columns/items,
  • the columns have variable lengths but all the rows must have the same length (i.e., ncol) except the last one, moreover in each column the increment betweeen items must equal ncol.

That said, it is possible to generate a sublist for each column using slicing, the length of the column is automatically the right one…, and eventually use sum to join the sub lists in the reordered one.

In [59]: from matplotlib.pyplot import subplots, show
    ...: reorder = lambda l, nc: sum((l[i::nc] for i in range(nc)), [])
    ...: 
    ...: f, ax = subplots(figsize=(6, 2), constrained_layout=True)
    ...: for i in range(1, 10):
    ...:     ax.plot((0,1),(0,1), label=str(i))
    ...: h, l = ax.get_legend_handles_labels()
    ...: ax.legend(reorder(h, 4), reorder(l, 4), ncol=4, loc=3)
    ...: show()

enter image description here

Answered By: gboffi
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.