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:

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

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.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With