why is the legend not present in the generated image if I use 'tight' for bbox_inches with the fig.legend method?

こ雲淡風輕ζ 提交于 2019-12-10 18:23:29

问题


I am trying to produce an image where I put the legend outside of the axes. But I find that if I use bbox_inches='tight' in the plt.savefig() method, the generated image does not contain the legend. A minimal working example to illustrate is as follows:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl

x = np.arange(-5, 5, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)


fig, ax1= plt.subplots(ncols=1, nrows=1, figsize=(10, 6))

ax1.plot(x, y1, label='sin(x)')
ax1.plot(x, y2, label='cos(x)')

handles, labels = ax1.get_legend_handles_labels()

plt.figlegend(handles, labels, loc='upper left', ncol=2, frameon=False,
              bbox_to_anchor=(0.11, 0.95))

plt.savefig('test.jpg', bbox_inches='tight')

The produced test.jpg is shown below

If I remove bbox_inches='tight' in savefig() method.(shown below), the legend is present in the produced image , but there are two much white space in the four side of the image.

Is there a good way to retain the tight layout of the image and also retain the legend in the generated image?

Edit 1

Following the instruction in this post, I also tried to use bbox_extra_artists argument in the savefig() method, something like this

legend = plt.figlegend(handles, labels, loc='lower left', ncol=2, frameon=True,
              bbox_to_anchor=(0.12, 0.88))
plt.savefig('test.jpg', bbox_extra_artists=(legend,), bbox_inches='tight')

As is pointed by @Diziet Asahi and @mportanceOfBeingErnest, if we use ax.legend() method, everything works fine. The following code works,

legend = ax1.legend(handles, labels, ncol=2, frameon=False,
                    loc='lower left', bbox_to_anchor=(-0.01, 1.2))
plt.savefig('test.jpg', bbox_inches='tight')

Edit2

According to the Matplotlib developer, there seems to be a bug that legend produced by fig.legend method are not taken into account when we use tight layout.


回答1:


You may create the legend using the .legend() method of one of the figure's axes. In order to specify the legend coordinates in figure coordinates, as would be done using figlegend you may use the bbox_transform argument.

ax1.legend(handles, labels, loc='upper left', ncol=2, frameon=False,
              bbox_to_anchor=(0.11, 0.95), bbox_transform=fig.transFigure)



回答2:


I can't tell exactly why it happens (seems like a bug to me), but it looks like the problem is with your use of the top-level plt.figlegend() function. The problem persist if using Figure.legend(), but disappears if you replace it with Axes.legend():

legend = ax1.legend(handles, labels, loc='lower left', ncol=2, frameon=False,
              bbox_to_anchor=(0,1.2))
fig.savefig('test.jpg', bbox_extra_artists=[legend], bbox_inches='tight')



来源:https://stackoverflow.com/questions/48128546/why-is-the-legend-not-present-in-the-generated-image-if-i-use-tight-for-bbox-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!