【问题标题】:how to remove the white space of invisiable axes in matplotlib during active plot?如何在活动绘图期间删除 matplotlib 中不可见轴的空白?
【发布时间】:2018-05-28 19:01:34
【问题描述】:

我想在活动绘图期间完全删除我的轴周围的空白(不是其他人要求的 save_fig )。 这里我们不能使用bbox_inches='tight'。我可以使用tight_layout(pad=0)。 当轴打开时,它工作正常,它显示所有刻度和 x-y 标签。 但是,在某些情况下,我将轴设置为关闭。我期望看到内容扩展以填充轴所在的空白空间。但是,这不起作用。它仍然保留填充,因为仍然有 x-y 标签和轴。 如何删除不可见轴对象的空白? 编辑:

我知道我可以使用 ax.set_yticks([])ax.set_xticks([]) 来关闭它们。但这很笨拙,我必须在清除蜱虫之前记住它们。如果我删除然后添加这些刻度。刻度不能再自动更新。 我想知道有没有更直接的方法可以做到这一点?

即使在移除所有刻度后,我们仍然可以看到边框间距很小。如果有人也可以想出一种方法来删除它。会很棒的。

如果有的话,我也想保留标题。因此硬编码的ax.set_position([0,0,1,x]) 不适合这种用法。当然,当有标题时,我们仍然可以尝试获取顶部间距,但是如果有人可以提供更直接/简单的方法来处理这个问题,那将是首选。

示例代码:

def demo_tight_layout(w=10, h=6, axisoff=False, removeticks=False):

    fig,ax = plt.subplots()
    fig.set_facecolor((0.8, 0.8, 0.8))
    rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
    ax.add_patch(rect)
    ax.plot([-w/2,w/2], [-h/2,h/2])
    ax.plot([-w/2,w/2], [h/2,-h/2])
    ax.set_ylabel("ylabel")
    ax.margins(0)
    _texts = []
    if axisoff:
        ax.set_axis_off()
        _texts.append("axisoff")
    if removeticks:
        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_ylabel("")
        _texts.append("removeticks")
    fig.text(0.5, 0.6, " ".join(_texts))

    fig.tight_layout(pad=0)
    plt.show()
    return fig, ax, text

【问题讨论】:

  • 请注意,如果仅描述问题,总是很难把握问题。相反,为什么不创建一个minimal reproducible example 来显示问题?
  • 您是作为脚本运行还是在控制台中运行它,或者您是否在例如使用内联绘图一个jupyter笔记本?每个案例可能都有自己的最佳解决方案。
  • 控制台/脚本。无需针对 jupyter 进行优化

标签: matplotlib


【解决方案1】:

您可以根据是否关闭轴来调整子图参数。

import matplotlib.pyplot as plt
from matplotlib import patches

def demo_tight_layout(w=10, h=6, axisoff=False):

    fig,ax = plt.subplots()
    fig.set_facecolor((0.8, 0.8, 0.8))
    rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
    ax.add_patch(rect)
    ax.plot([-w/2,w/2], [-h/2,h/2])
    ax.plot([-w/2,w/2], [h/2,-h/2])
    ax.set_ylabel("ylabel")
    ax.margins(0)
    _texts = []

    fig.tight_layout()
    if axisoff:
        ax.set_axis_off()
        _texts.append("axisoff")
        params = dict(bottom=0, left=0, right=1)
        if ax.get_title() == "":
            params.update(top=1)
        fig.subplots_adjust(**params)

    fig.text(0.5, 0.6, " ".join(_texts))

    plt.show()

现在demo_tight_layout(axisoff=True) 产生

demo_tight_layout(axisoff=False) 产生

【讨论】:

    【解决方案2】:

    您需要设置坐标轴位置以填充图形。如果你用

    创建你的图形和绘图
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.gca()
    ax.plot(some_x_data, some_y_data)
    

    您需要添加以下行以用轴填充图形:

    ax.set_position([0, 0, 1, 1], which='both')
    

    这通过以下方式设置相对于图形大小的坐标轴位置:

    [left, bottom, width, height]
    

    所以要完全填充图形,请使用[0, 0, 1, 1],如上所示。

    所以拿你的代码,它应该看起来像这样(使用fill_figure bool 来检查):

    def demo_tight_layout(w=10, h=6, axisoff=False, removeticks=False, fill_figure=False):
    
        fig,ax = plt.subplots()
        fig.set_facecolor((0.8, 0.8, 0.8))
        rect = patches.Rectangle((-w/2, -h/2), w, h, color='#00ffff', alpha=0.5)
        ax.add_patch(rect)
        ax.plot([-w/2,w/2], [-h/2,h/2])
        ax.plot([-w/2,w/2], [h/2,-h/2])
        ax.set_ylabel("ylabel")
        ax.margins(0)
        _texts = []
        if axisoff:
            ax.set_axis_off()
            _texts.append("axisoff")
        if removeticks:
            ax.set_xticks([])
            ax.set_yticks([])
            ax.set_ylabel("")
            _texts.append("removeticks")
        fig.text(0.5, 0.6, " ".join(_texts))
    
        fig.tight_layout(pad=0)
        if fill_figure:
            ax.set_position([0, 0, 1, 1], which='both')
        plt.show()
        return fig, ax, text
    

    ax.set_position 必须在fig.tight_layout 之后。 如果需要图形标题,则没有直接的方法。不幸的是,这是无法避免的。您需要手动调整height 参数,以便标题适合图中,例如:

    ax.set_position([0, 0, 1, .9], which='both')
    

    【讨论】:

    • 问题是,当有标题时,这会让它消失。
    • 如果你想要一个标题,你需要做一个解决方法,比如:ax.set_position([0, 0, 1, .9], which='both')
    • 我不喜欢这种硬编码的间距,当您允许人们更改字体大小并具有多行标题时,这非常笨拙。
    • 是的,我也没有。但不幸的是,没有简单的解决方法。这是matplotlib的问题。恕我直言,最简单的解决方法是将图形保存为 svg,在像 Inkscape 这样的 svg 编辑器中打开它,标记透明背景,删除它并将 Inkscape 文档调整为图形大小。很抱歉,这是最简单的方法。