How to disable bbox_inches='tight' when wo

2019-06-20 23:21发布

When work with matplotlib inline backend in ipython notebook, the default behavior is using bbox_inches='tight' to generate the embedded png image internally via savefig(). This eliminates the whitespace around the axes and is great in most cases.

However, sometimes one might want to (temporarily) disable this feature, for example, when (s)he wants to manually keep two figures vertically aligned (assume that we don't want to use subplot here):

%matplotlib inline
from pylab import *
plot(rand(100))
subplots_adjust(left=0.2) # Has no effect with inline, but works as expected with qt
figure()
plot(rand(100)*10000) # Will result in a larger left margin for this figure...
subplots_adjust(left=0.2)

So how to disable this behavior? Thanks~

EDIT

To make the issue involved here more explicit (thanks to Anzel), the 2nd figure, due to more digits to be displayed in yticklabels, will have larger left margin (and smaller right margin) after automatic layout adjustment triggered by the bbox_inches='tight' option in savefig(), which is internally called by notebook to generate the embedded png output. It will effectively truncate any additional space I intentionally make with subplots_adjust(), so that the 2nd figure will seem to be shifted to the right, and not vertically "aligned" with the 1st figure.

It is easy to see what I mean---just try the code snippet above:)

The reason why I'm not using subplot/subplots here (see comments to Anzel's answer) is that in this particular case, the two figures are acutally themselves composed of tens of small subplots, plus some additional formatting/labeling. Merging them into one larger array of subplots is not trivial...

2条回答
可以哭但决不认输i
2楼-- · 2019-06-20 23:32

There's a fuller answer here: Matplotlib and Ipython-notebook: Displaying exactly the figure that will be saved

The trick is to turn off the bbox_inches='tight' setting in ipython. It's a bit awkward to do temporarily, but just run the IPython magic in a block: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}

If you want to switch back to the normal way, where axis labels are automatically never cut, you can run %config InlineBackend.print_figure_kwargs = {'bbox_inches':'tight'} but it has to be after the block where you do the plotting that needs precise bounding boxes.

查看更多
聊天终结者
3楼-- · 2019-06-20 23:57

You may use pyplot.subplots to align the plots in a grid order, so the figures will be visually aligned in notebook (if that's what you want?)

Something like this:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

d1 = np.random.rand(100)
d2 = np.random.rand(100)*10000

fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1)
plt.subplots_adjust(left=0.2)
ax1.plot(d1)
ax2.plot(d2)

Updates

As OP's requirements to use separate plots rather than subplots, here is a hacky solution. This is working on my Notebook, more details about the customization can be found HERE.

import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

# to override ytick.major.width before any plot
plt.rcParams['ytick.major.pad'] = 20
plt.plot(np.random.rand(100))

# another override to set alignment for the plot 
plt.rcParams['ytick.major.pad'] = 5
plt.figure()
plt.plot(np.random.rand(100)*10000)

The Plots

# plt.rcdefaults() will reset everything to defaults as the doc says.

Not the most elegant way but it's working as required.

查看更多
登录 后发表回答