1

I need the plot legend to appear side-by-side to the plot axes, i.e. outside of the axes and non-overlapping.

The width of the axes and the legend should adjust "automatically" so that they both fill the figure w/o them to overlap or the legend to be cut, even when using tight layout. The legend should occupy a minor portion of the figure (let's say max to 1/3 of figure width so that the remaining 2/3 are dedicated to the actual plot).

Eventually, the font of the legend entries can automatically reduce to meet the requirements.

I've read a number of answers regarding legend and bbox_to_anchor in matplotlib with no luck, among which:

I tried by creating a dedicated axes in which to put the legend so that plt.tight_layout() would do its job properly but then the legend only takes a minor portion of the dedicated axes, with the result that a lot of space is wasted. Or if there isn't enough space (the figure is too small), the legend overlaps the first axes anyway.

import matplotlib.pyplot as plt
import numpy as np

# generate some data
x = np.arange(1, 100) 

# create 2 side-by-side axes
fig, ax = plt.subplots(1,2)
# create a plot with a long legend 
for ii in range(20):
    ax[0].plot(x, x**2, label='20201110_120000')
    ax[0].plot(x, x, label='20201104_110000')

# grab handles and labels from the first ax and pass it to the second
hl = ax[0].get_legend_handles_labels() 
leg = ax[1].legend(*hl, ncol=2)
plt.tight_layout()

I'm open to use a package different from matplotlib.

Robyc
  • 379
  • 1
  • 13

1 Answers1

2

Instead of trying to plot the legend in a separate axis, you can pass loc to legend:

# create 2 side-by-side axes
fig, ax = plt.subplots(figsize=(10,6))
# create a plot with a long legend 
for ii in range(20):
    ax.plot(x, x**2, label='20201110_120000')
    ax.plot(x, x, label='20201104_110000')

# grab handles and labels from the first ax and pass it to the second
ax.legend(ncol=2, loc=[1,0])
plt.tight_layout()

Output:

enter image description here

Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
  • Ah! I tried this option with the `Figure legend` instead of the `Axes legend`, which is not good. Using `loc=[1, 0]` with the `Figure legend` puts the legend outside the Figure itself, thus it's invisible. Using `Axes legend` works as expected. – Robyc Nov 11 '20 at 09:56