This question is similar to this one asked 6 years ago. However, their solution is not quite solving my problem; unlike their question, I am dealing with multiple legends, some of which are getting cut off.
I'm trying to create a figure containing multiple legends that sit outside the axes of my graph. I'm following the matplotlib documentation's instructions for creating multiple legends, using add_artist
to add all but the final legend to my axes. I then use the bbox_extra_artists
parameter in my savefig
call as described in the above question to include all my legend objects. As seen in this example output image, the wider legend still gets cut off on the right side.
The code used to generate this plot:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.gca()
for x in [0, 1, 2]:
ax.bar(x+0.5, x+1, width=1, color=['red', 'blue', 'green'][x])
handle1 = plt.Line2D((0,1), (0,0), color='purple')
lgd1 = ax.legend([handle1], ['label1 is very long'], bbox_to_anchor=(1, 1))
ax.add_artist(lgd1)
handle2 = plt.Line2D((0,1), (0,0), color='orange')
lgd2 = ax.legend([handle2], ['label2'], bbox_to_anchor=(1, 0.9))
plt.savefig('output.png', bbox_extra_artists=(lgd1,lgd2), bbox_inches='tight')
Notably, if I change the order in which the legends are added (adding the wider legend first), the problem goes away and both legends are visible as seen here:
handle2 = plt.Line2D((0,1), (0,0), color='orange')
lgd2 = ax.legend([handle2], ['label2'], bbox_to_anchor=(1, 0.9))
ax.add_artist(lgd2)
handle1 = plt.Line2D((0,1), (0,0), color='purple')
lgd1 = ax.legend([handle1], ['label1 is very long'], bbox_to_anchor=(1, 1))
plt.savefig('output.png', bbox_extra_artists=(lgd1,lgd2), bbox_inches='tight')
For my actual project (which has to handle a dynamic number of legends), I've made it figure out which legend is "longest" and always add that legend last to work around this problem. However, this feels messy and it doesn't allow for adding more legends on other sides of the figure (e.g., I cannot add an x-axis legend below the graph without it getting cut off, since only one legend can be added "last").
Is this an intractable bug in matplotlib, or is there a tidy solution I'm missing?