Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib legend + tight_layout = squashed subplots

Consider the following example:

import matplotlib.pyplot as plt
from matplotlib import gridspec
import numpy as np

x = np.linspace(0, 10, 100)
y = 2*x + 0.5

plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(2, 2)

plt.subplot(gs[0, 0])
plt.plot(x, y, "o")

plt.subplot(gs[0, 1])
plt.plot(x, y, "o")

plt.subplot(gs[1, :])
plt.plot(x, y, "o", label="test")
plt.legend(loc="upper center", bbox_to_anchor=(0.5, 2.7))

plt.subplot(gs[2, :])
plt.plot(x, y, "o")

plt.tight_layout()
plt.show()

When I remove bbox_to_anchor from plt.legend, the above code should produce something like this:

enter image description here

But when I place the legend outside of the subplot using bbox_to_anchor (as in the code above), the subplots get squashed:

enter image description here

Obviously, this is not desired. There seems to be a conflict between bbox_to_anchor and tight_layout() (if you remove either from the code above, something sensible comes out). Is there something I'm doing wrong, or is this known/expected behaviour?

This problem is reproduced under various back-ends. I don't get any warnings or errors. I'm using matplotlib version 2.2.2.

like image 267
MPA Avatar asked Aug 31 '25 02:08

MPA


1 Answers

The result is expected, although clearly not desireable. Since the legend is part of the lower subplot, it will take part in the tight_layout mechanism and hence shift everything to the top.

You may call tight_layout first,

plt.tight_layout()
plt.legend(loc="upper center", bbox_to_anchor=(0.5, 2.3))

to get the tight spacing and then afterwards create the legend.

You may also create a figure legend,

fig = plt.figure(figsize=(6, 4))
# ...
fig.legend(loc="upper center", bbox_to_anchor=(0.5, .9))
plt.tight_layout()
like image 169
ImportanceOfBeingErnest Avatar answered Sep 02 '25 14:09

ImportanceOfBeingErnest