简体   繁体   English

添加自定义刻度和标签

[英]Adding a custom tick and label

I would like to add a custom major tick and label in matplotlib.我想在 matplotlib 中添加一个自定义的主要刻度和标签。 A typical use is to add a label at the location math.pi with the label "$\\pi$" .一个典型的用途是在math.pi位置添加一个标签,标签为"$\\pi$" My aim is to leave the other ticks as is: I would like to retain the original major and minor ticks with the formatting that have been previously chosen but with this extra tick and label.我的目标是保持其他刻度不变:我想保留原始的主要和次要刻度以及先前选择的格式,但带有这个额外的刻度和标签。 I have figured out a way (and found posts on these forums) to add the tick:我想出了一种方法(并在这些论坛上找到了帖子)来添加勾号:

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

My trouble is with the label.我的问题是标签。 I have tried to retrieve the labels in a similar way with ax.xaxis.get_majorticklabels() but that gives me a list of matplotlib.text.Text which I am unsure how to deal with.我试图用ax.xaxis.get_majorticklabels()以类似的方式检索标签,但这给了我一个matplotlib.text.Text的列表,我不确定如何处理。 My intention was to get the list of labels as strings, to add the new label (at the correct position) and then use ax.xaxis.set_ticklabels(list_label) in a way that is similar to the location.我的目的是将标签列表作为字符串获取,添加新标签(在正确的位置),然后以类似于位置的方式使用ax.xaxis.set_ticklabels(list_label)

This is what I usually do, though I've never been completely satisfied with the approach. 这是我通常所做的,尽管我从未完全满意此方法。 There may be a better way, without calling draw() . 没有调用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()

在此处输入图片说明

I"m late to the party, but here's my solution, which preserves the original automatic tick location and formatting (or whatever Locator/Formatter you set on the axes), and simply adds new ticks. The solution also works when you move the view, ie when dragging or zooming in a GUI.我迟到了,但这是我的解决方案,它保留了原始的自动刻度位置和格式(或您在轴上设置的任何定位器/格式器),并且只需添加新刻度。该解决方案在您移动视图时也有效, 即在 GUI 中拖动或放大时。

I basically implement a new Locator and a new Formatter that chain to original ones.我基本上实现了一个新的定位器和一个链接到原始定位器的新格式器。

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)

These two can be used like any other Locator/Formatter directly, or with this little helper method这两个可以像任何其他定位器/格式化程序一样直接使用,或者使用这个小助手方法

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

Example usage:用法示例:

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$'
})

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM