【问题标题】:How to disable bbox_inches='tight' when working with matplotlib inline in ipython notebook在 ipython 笔记本中使用 matplotlib 内联时如何禁用 bbox_inches='tight'
【发布时间】:2014-11-03 12:43:11
【问题描述】:

在 ipython notebook 中使用 matplotlib 内联后端时,默认行为是使用 bbox_inches='tight' 通过 savefig() 在内部生成嵌入的 png 图像。这消除了轴周围的空白,在大多数情况下都很好。

但是,有时可能想要(暂时)禁用此功能,例如,当他想要手动保持两个图形垂直对齐时(假设我们不想在这里使用子图):

%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)

那么如何禁用这种行为呢?谢谢~

编辑

为了使这里涉及的问题更加明确(感谢 Anzel),由于 yticklabels 中要显示的数字更多,第二个数字在 bbox_inches 触发的自动布局调整后将具有更大的左边距(和更小的右边距) savefig() 中的 ='tight' 选项,由 notebook 内部调用以生成嵌入的 png 输出。它会有效地截断我用 subplots_adjust() 故意创建的任何额外空间,因此第二个图形似乎向右移动,而不是与第一个图形垂直“对齐”。

很容易理解我的意思——试试上面的代码 sn-p :)

我在这里不使用 subplot/subplots 的原因(请参阅 cmets 对 Anzel 的回答)是在这种特殊情况下,这两个数字实际上是由数十个小的 subplots 组成的,加上一些额外的格式/标签。将它们合并到一个更大的子图数组中并非易事......

【问题讨论】:

  • 你为什么不使用matplotlib.pyplot
  • 只是为了方便。我认为 matplotlib.pyplot.plot 和 pylab.plot 是等价的。
  • pyplot是matplotlib内置的,不一定要导入pylab,就是我的意思
  • 更多问题,我不认为我完全得到你想要实现的目标,你想在笔记本中动态设置轴标签更窄和更宽?
  • 本质上,我想改变坐标轴的左边距(从默认的 0.1 到 0.2),以便在笔记本中视觉上对齐两个图形的坐标轴框架/bbox。

标签: python matplotlib ipython ipython-notebook


【解决方案1】:

这里有更完整的答案:Matplotlib and Ipython-notebook: Displaying exactly the figure that will be saved

诀窍是关闭 ipython 中的bbox_inches='tight' 设置。暂时做起来有点别扭,不过还是分块运行IPython魔法吧:%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}

如果您想切换回正常方式,即不会自动切割轴标签,您可以运行%config InlineBackend.print_figure_kwargs = {'bbox_inches':'tight'},但它必须在您进行需要精确边界框的绘图的块之后。

【讨论】:

    【解决方案2】:

    您可以使用pyplot.subplots 将图表按网格顺序对齐,这样这些图形将在笔记本中直观地对齐(如果这是您想要的?)

    类似这样的:

    %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)
    

    更新

    由于 OP 要求使用单独的图而不是子图,这是一个 hacky 解决方案。这是在我的笔记本上运行的,有关自定义的更多详细信息可以找到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)
    

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

    不是最优雅的方式,但它可以按要求工作。

    【讨论】:

    • 谢谢,Anzel~ subplot/subplots 确实是显而易见的方法。但是,正如我在问题中提到的,有时我们不想使用此选项。就我而言,这两个数字本身由数十个小子图组成,加上一些额外的格式/标签。将它们合并到一个更大的子图数组中并非易事,因此最好在图形级别进行操作。唯一需要做的是调整轴的左边距,这很容易在 qt 后端使用 subplots_adjust 。但是对于内联后端,内部使用的 bbox_inches='tight' 选项会干扰这一点。
    • @herrlich10,我终于找到了一个相当老套的解决方案。查看我的更新
    最近更新 更多