简体   繁体   English

Matplotlib:添加字符串作为自定义x-ticks但是还保留现有(数字)刻度标签? matplotlib.pyplot.annotate的替代品?

[英]Matplotlib: Add strings as custom x-ticks but also keep existing (numeric) tick labels? Alternatives to matplotlib.pyplot.annotate?

I am trying to produce a graph and I am having some issues annotating it. 我试图生成一个图表,我有一些问题注释它。

My graph has a log scale on the x-axis, showing time. 我的图表在x轴上有一个对数刻度,显示时间。 What I want to be able to do is keep the existing (but not predictable) numeric tick labels at 100 units, 1000 units, 10000 units, etc but also add custom tick labels to the x-axis that make it clear where more "human readable" time intervals occur---for instance I want to be able to label 'one week', 'one month', '6 months', etc. 我希望能够做的是将现有(但不可预测)的数字刻度标签保持在100个单位,1000个单位,10000个单位等,还要在x轴上添加自定义刻度标签,以便更清楚“人类”可读的“时间间隔发生 - 例如我希望能够标记'一周','一个月','六个月'等。

I can use matplotlib.pyplot.annotate() to mark the points but it doesn't really do what I want. 我可以使用matplotlib.pyplot.annotate()来标记点,但它并没有真正做我想要的。 I don't really want text and arrows on top of my graph, I just want to add a few extra custom tick marks. 我真的不想在图表上方放置文字和箭头,我只想添加一些额外的自定义刻度标记。 Any ideas? 有任何想法吗?

If you really want to add extra ticks, you can get the existing ones using axis.xaxis.get_majorticklocs() , add whatever you want to add, and then set the ticks using axis.xaxis.set_ticks(<your updated array>) . 如果你真的想添加额外的刻度,你可以使用axis.xaxis.get_majorticklocs()获取现有的axis.xaxis.get_majorticklocs() ,添加你想要添加的内容,然后使用axis.xaxis.set_ticks(<your updated array>)设置刻度。

An alternative would be to add vertical lines using axvline . 另一种方法是使用axvline添加垂直线。 The advantage is that you don't have to worry about inserting your custom tick into the existing array, but you'll have to annotate the lines manually. 优点是您不必担心将自定义tick插入现有数组,但您必须手动注释这些行。

Yet another alternative would be to add a linked axis with your custom ticks. 另一种替代方法是使用您的自定义刻度添加链接轴。

From http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.xticks : 来自http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.xticks

# return locs, labels where locs is an array of tick locations and
# labels is an array of tick labels.
locs, labels = xticks()

So all you should need to do is obtain the locs and labels and then modify labels to your liking (dummy example): 所以你需要做的就是获取locslabels ,然后根据自己的喜好修改labels (虚拟示例):

labels = ['{0} (1 day)','{0} (1 weak)', '{0} (1 year)']
new_labels = [x.format(locs[i]) for i,x  in enumerate(labels)]

and then run: 然后运行:

xticks(locs, new_labels)

This is my solution. 这是我的解决方案。 The main advantages are: 主要优点是:

  • You can specify the axes (useful for twin axes or if working with multiple axes simultaneously) 您可以指定轴(对于双轴或同时使用多个轴有用)
  • You can specify the axis (put ticks on x-axis or y-axis) 您可以指定轴(在x轴或y轴上放置刻度)
  • You can easily add new ticks while keeping the automatic ones 您可以轻松添加新的刻度,同时保留自动刻度
  • It automatically replaces if you add a tick that already exists. 如果添加已存在的勾号,它会自动替换。

Code: 码:

#!/usr/bin/python
from __future__ import division
import matplotlib.pyplot as plt
import numpy as np

#Function to add ticks
def addticks(ax,newLocs,newLabels,pos='x'):
    # Draw to get ticks
    plt.draw()

    # Get existing ticks
    if pos=='x':
        locs = ax.get_xticks().tolist()
        labels=[x.get_text() for x in ax.get_xticklabels()]
    elif pos =='y':
        locs = ax.get_yticks().tolist()
        labels=[x.get_text() for x in ax.get_yticklabels()]
    else:
        print("WRONG pos. Use 'x' or 'y'")
        return

    # Build dictionary of ticks
    Dticks=dict(zip(locs,labels))

    # Add/Replace new ticks
    for Loc,Lab in zip(newLocs,newLabels):
        Dticks[Loc]=Lab

    # Get back tick lists
    locs=list(Dticks.keys())
    labels=list(Dticks.values())

    # Generate new ticks
    if pos=='x':
        ax.set_xticks(locs)
        ax.set_xticklabels(labels)
    elif pos =='y':
        ax.set_yticks(locs)
        ax.set_yticklabels(labels)


#Get numpy arrays
x=np.linspace(0,2)
y=np.sin(4*x)

#Start figure
fig = plt.figure()
ax=fig.add_subplot(111)

#Plot Arrays
ax.plot(x,y)
#Add a twin axes
axr=ax.twinx()

#Add more ticks
addticks(ax,[1/3,0.75,1.0],['1/3','3/4','Replaced'])
addticks(axr,[0.5],['Miguel'],'y')

#Save figure
plt.savefig('MWE.pdf')  

I like Miguel's answer above. 我喜欢上面的Miguel的回答。 Worked quite well. 工作得很好。 However, a small adjustment has to be made. 但是,必须进行小幅调整。 The following: 下列:

# Get back tick lists
locs=Dticks.keys()
labels=Dticks.values()

must be changed to 必须改为

# Get back tick lists
locs=list(Dticks.keys())
labels=list(Dticks.values())

since, in Python 2.7+/3, Dict.keys() and Dict.values() return dict_keys and dict_values objects, which matplotlib does not like (apparently). 因为,在Python 2.7 + / 3中,Dict.keys()和Dict.values()返回dict_keys和dict_values对象,matplotlib不喜欢(显然)。 More about those two objects in PEP 3106 . 更多关于PEP 3106中的这两个对象。

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

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