代码之家  ›  专栏  ›  技术社区  ›  Mad Physicist

保存地物时,记号标签将被覆盖

  •  0
  • Mad Physicist  · 技术社区  · 6 年前

    我在胡乱画“传统”相交轴:

    x = range(-1, 2)
    y = range(-1, 2)
    fig, ax = plt.subplots()
    ax.spines['left'].set_position('zero')
    ax.spines['bottom'].set_position('zero')
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.1))
    ax.xaxis.set_major_locator(ticker.MultipleLocator(0.5))
    ax.yaxis.set_minor_locator(ticker.MultipleLocator(0.1))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(0.5))
    ax.plot(x, y)
    

    这工作正常:

    enter image description here

    fig.canvas.draw()  # Force the ticks to be computed now
    next(tick for tick in ax.yaxis.get_major_ticks()
         if tick.get_loc() == 0.0).set_visible(False)
    plt.setp(next(tick for tick in ax.xaxis.get_major_ticks()
                  if tick.get_loc() == 0.0).label, ha='right', text='0  ')
    

    这个 几乎 作品:

    enter image description here

    y轴零点被移除,x轴零点被正确对齐。但是标签没有从 0.0 0 一如预期。

    fig.savefig() ,标签确实正确。但是,保存图形时会重新格式化。如何正确更改标签,使其显示 在图像中?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Mad Physicist    6 年前

    我会解决这个问题。

    1. 0
    2. 您要移动标签。

    一个想法可以是将 ScalarFormatter 并让它为零位置返回一个自定义标签。这可以是一个空字符串,也可以是按您希望的方式格式化的数字0。

    from matplotlib import ticker as mticker
    class CustomTicker(mticker.ScalarFormatter):
        def __init__(self, zero="0", **kwargs):
            self.zero=zero
            mticker.ScalarFormatter.__init__(self, **kwargs)
        def __call__(self, x, pos=None):
            if x != 0:
                return mticker.ScalarFormatter.__call__(self, x, pos)
            else:
                return self.zero
    
    ax.xaxis.set_major_formatter(CustomTicker(zero="0"))
    ax.yaxis.set_major_formatter(CustomTicker(zero=""))
    

    在这里使用格式化程序的优点可以理解如下。标签(即 Text 画布上的实例)在绘制图形之前,不会为其设置固定的字符串。然后,在每次后续绘制之后,该字符串可能会发生变化,这取决于轴的限制或图形大小的变化。在幕后,定位器确定记号的位置。然后将记号标签放置在记号旁边。然后,格式化程序根据位置设置标签的字符串。这是通过调用具有位置的格式化程序来完成的 x "-10" . 更改轴的限制(例如,通过缩放)时,可能会将同一个标签放置在位置x=-20处。然后,对格式化程序的调用会确保其文本更新为显示 "-20" 也。 "-10"

    虽然标签的许多属性是以集中的方式设置的,但它们的实际转换不是这样的。因此,人们可以通过变换来翻译单个标签。在这里,我们可以选择在像素空间(即。 之后 执行主变换)。由于单个标签在更改限制时(即缩放或平移时)可能会更改其内容,因此我们可以创建一个回调来更改一个标签在零位置的变换,而不受实际限制的影响。 下面我们将 "0" 通过 -10 像素。

    import matplotlib.transforms as mtrans
    
    basetrans = ax.get_xticklabels()[0].get_transform()
    def movelabel(evt=None):
        trans = basetrans + mtrans.Affine2D().translate(-10,0)
        for tick in ax.xaxis.get_major_ticks():
            if tick.get_loc() == 0.0:
                tick.label.set_transform(trans)
            else:
                tick.label.set_transform(basetrans)
    
    fig.canvas.draw()
    movelabel()
    ax.callbacks.connect('xlim_changed', movelabel)
    ax.callbacks.connect('ylim_changed', movelabel)
    

    import matplotlib.pyplot as plt
    from matplotlib import ticker as mticker
    
    x = range(-1, 2)
    y = range(-1, 2)
    fig, ax = plt.subplots()
    ax.spines['left'].set_position('zero')
    ax.spines['bottom'].set_position('zero')
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.xaxis.set_minor_locator(mticker.MultipleLocator(0.1))
    ax.xaxis.set_major_locator(mticker.MultipleLocator(0.5))
    ax.yaxis.set_minor_locator(mticker.MultipleLocator(0.1))
    ax.yaxis.set_major_locator(mticker.MultipleLocator(0.5))
    
    ax.plot(x, y)
    
    from matplotlib import ticker as mticker
    class CustomTicker(mticker.ScalarFormatter):
        def __init__(self, zero="0", **kwargs):
            self.zero=zero
            mticker.ScalarFormatter.__init__(self, **kwargs)
        def __call__(self, x, pos=None):
            if x != 0:
                return mticker.ScalarFormatter.__call__(self, x, pos)
            else:
                return self.zero
    
    ax.xaxis.set_major_formatter(CustomTicker(zero="0"))
    ax.yaxis.set_major_formatter(CustomTicker(zero=""))
    
    
    import matplotlib.transforms as mtrans
    
    basetrans = ax.get_xticklabels()[0].get_transform()
    def movelabel(evt=None):
        trans = basetrans + mtrans.Affine2D().translate(-10,0)
        for tick in ax.xaxis.get_major_ticks():
            if tick.get_loc() == 0.0:
                tick.label.set_transform(trans)
            else:
                tick.label.set_transform(basetrans)
    
    fig.canvas.draw()
    movelabel()
    ax.callbacks.connect('xlim_changed', movelabel)
    ax.callbacks.connect('ylim_changed', movelabel)
    
    plt.show()
    

    enter image description here

        2
  •  1
  •   Sheldore    6 年前

    这里有一个解决方案:

    • 用你的方法隐藏 任何一个 y标签。
    • '0.0' 字符串加整数 0 . 我用 [1:-1] 因为 get_text() $ 作为 $-1.0$ , $0.0$ , $1.0$ 等。
    • 最后重置x或y标签。

    躲藏 0.0 从x轴

    fig.canvas.draw()  # Force the ticks to be computed now
    next(tick for tick in ax.xaxis.get_major_ticks()
         if tick.get_loc() == 0.0).set_visible(False)
    
    labels = [item.get_text()[1:-1] for item in ax.get_yticklabels()]
    new_labels = [ "%d" % int(float(l)) if l == '0.0' else l for l in labels]
    ax.set_yticklabels(new_labels)
    ax.set_title('Hiding the 0.0 from x-axis')
    

    enter image description here

    躲藏 0 从y轴

    fig.canvas.draw()  # Force the ticks to be computed now
    next(tick for tick in ax.yaxis.get_major_ticks()
         if tick.get_loc() == 0.0).set_visible(False)
    
    labels = [item.get_text()[1:-1] for item in ax.get_xticklabels()]
    new_labels = [ "%d" % int(float(l)) if l == '0.0' else l for l in labels]
    ax.set_xticklabels(new_labels)
    ax.set_title('Hiding the 0.0 from y-axis')
    

    enter image description here