【问题标题】:Adding a custom tick and label添加自定义刻度和标签
【发布时间】:2014-04-10 08:32:28
【问题描述】:

我想在 matplotlib 中添加一个自定义的主要刻度和标签。一个典型的用途是在math.pi 位置添加一个标签,标签为"$\pi$"。我的目标是保持其他刻度不变:我想保留原来的主要和次要刻度,其格式之前已选择,但带有这个额外的刻度和标签。我想出了一种方法(并在这些论坛上找到了帖子)来添加勾号:

list_loc=list(ax.xaxis.get_majorticklocs())
list_loc.append(pos)
list_loc.sort()
ax.xaxis.set_ticks(list_loc)

我的麻烦在于标签。我尝试使用ax.xaxis.get_majorticklabels() 以类似的方式检索标签,但这给了我一个matplotlib.text.Text 的列表,我不确定如何处理。我的意图是将标签列表作为字符串获取,添加新标签(在正确的位置),然后以类似于位置的方式使用ax.xaxis.set_ticklabels(list_label)

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    我迟到了,但这是我的解决方案,它保留了原始的自动刻度位置和格式(或您在轴上设置的任何定位器/格式化程序),并简单地添加新刻度。该解决方案也适用于您移动视图,即在 GUI 中拖动或缩放时。

    我基本上实现了一个新的定位器和一个链接到原始定位器的新格式化器。

    import matplotlib.ticker as mticker
    class AdditionalTickLocator(mticker.Locator):
        '''This locator chains whatever locator given to it, and then add addition custom ticks to the result'''
        def __init__(self, chain: mticker.Locator, ticks) -> None:
            super().__init__()
            assert chain is not None
            self._chain = chain
            self._additional_ticks = np.asarray(list(ticks))
    
        def _add_locs(self, locs):
            locs = np.unique(np.concatenate([
                np.asarray(locs),
                self._additional_ticks
            ]))
            return locs
    
        def tick_values(self, vmin, vmax):
            locs = self._chain.tick_values(vmin, vmax)
            return self._add_locs(locs)
    
        def __call__(self):
            # this will call into chain's own tick_values,
            # so we also add ours here
            locs = self._chain.__call__()
            return self._add_locs(locs)
    
        def nonsingular(self, v0, v1):
            return self._chain.nonsingular(v0, v1)
        def set_params(self, **kwargs):
            return self._chain.set_params(**kwargs)
        def view_limits(self, vmin, vmax):
            return self._chain.view_limits(vmin, vmax)
    
    
    class AdditionalTickFormatter(mticker.Formatter):
        '''This formatter chains whatever formatter given to it, and
        then does special formatting for those passed in custom ticks'''
        def __init__(self, chain: mticker.Formatter, ticks) -> None:
            super().__init__()
            assert chain is not None
            self._chain = chain
            self._additional_ticks = ticks
    
        def __call__(self, x, pos=None):
            if x in self._additional_ticks:
                return self._additional_ticks[x]
            res = self._chain.__call__(x, pos)
            return res
    
        def format_data_short(self, value):
            if value in self._additional_ticks:
                return self.__call__(value)
            return self._chain.format_data_short(value)
    
        def get_offset(self):
            return self._chain.get_offset()
        
        def _set_locator(self, locator):
            self._chain._set_locator(locator)
    
        def set_locs(self, locs):
            self._chain.set_locs(locs)
    

    这两个可以像任何其他定位器/格式化程序一样直接使用,或者与这个小助手方法一起使用

    def axis_add_custom_ticks(axis, ticks):
        locator = axis.get_major_locator()
        formatter = axis.get_major_formatter()
        axis.set_major_locator(AdditionalTickLocator(locator, ticks.keys()))
        axis.set_major_formatter(AdditionalTickFormatter(formatter, ticks))
    

    示例用法:

    fig, ax = plt.subplots()
    x = np.linspace(0,10,1000)
    ax.plot(x,np.exp(-(x-np.pi)**2))
    
    axis_add_custom_ticks(ax.xaxis, {
        np.pi: '$\pi$'
    })
    

    【讨论】:

      【解决方案2】:

      这是我通常会做的事情,尽管我从未对这种方法完全满意。可能有更好的方法,无需调用draw()

      fig,ax=plt.subplots()
      x=linspace(0,10,1000)
      x.plot(x,exp(-(x-pi)**2))
      plt.draw() # this is required, or the ticklabels may not exist (yet) at the next step
      labels = [w.get_text() for w in ax.get_xticklabels()]
      locs=list(ax.get_xticks())
      labels+=[r'$\pi$']
      locs+=[pi]
      ax.set_xticklabels(labels)
      ax.set_xticks(locs)
      ax.grid()
      plt.draw()
      

      【讨论】:

      • 这似乎行得通。我试过 get_text() 方法,但我没有调用 plt.draw() 方法,我很困惑。我仍然想知道是否没有其他方法。让我们等待其他可能的答案...
      • 假设我想将新标签向下移动一点。有可能吗?
      猜你喜欢
      • 2016-01-07
      • 2018-04-29
      • 1970-01-01
      • 2012-05-08
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      相关资源
      最近更新 更多