Matplotlib: добавьте строки как пользовательские x-тики, но также сохраните существующие (числовые) метки метки? Альтернативы matplotlib.pyplot.annotate?
Я пытаюсь создать график, и у меня есть некоторые вопросы, аннотирующие его.
Мой график имеет масштаб шкалы на оси x, показывающий время. То, что я хочу сделать, это сохранить существующие (но не предсказуемые) числовые метки меток на 100 единиц, 1000 единиц, 10000 единиц и т.д., Но также добавить пользовательские метки ярлыков к оси X, которые позволят понять, где больше "человеческих читаемые" промежутки времени - например, я хочу иметь возможность отмечать "одну неделю", "один месяц", "6 месяцев" и т.д.
Я могу использовать matplotlib.pyplot.annotate(), чтобы отмечать точки, но это действительно не то, что я хочу. Мне не нужен текст и стрелки поверх моего графика, я просто хочу добавить несколько дополнительных пользовательских меток. Любые идеи?
Ответы
Ответ 1
Если вы действительно хотите добавить дополнительные тики, вы можете получить существующие с помощью axis.xaxis.get_majorticklocs()
, добавить все, что хотите добавить, а затем установить тики с помощью axis.xaxis.set_ticks(<your updated array>)
.
Альтернативой может быть добавление вертикальных линий с помощью axvline
. Преимущество состоит в том, что вам не нужно беспокоиться о том, чтобы вставить свой собственный тик в существующий массив, но вам придется вручную аннотировать строки.
Еще одна альтернатива - добавить связанную ось с вашими пользовательскими тиками.
Ответ 2
Из 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()
Итак, все, что вам нужно нужно сделать, это получить locs
и labels
, а затем изменить labels
по своему вкусу (фиктивный пример):
labels = ['{0} (1 day)','{0} (1 weak)', '{0} (1 year)']
new_labels = [x.format(locs[i]) for i,x in enumerate(labels)]
а затем запустите:
xticks(locs, new_labels)
Ответ 3
Это мое решение. Основные преимущества:
- Вы можете указать оси (полезно для двойных осей или одновременно работать с несколькими осями)
- Вы можете указать ось (пометить галочки по оси x или оси y)
- Вы можете легко добавлять новые тики, сохраняя при этом автоматические
- Он автоматически заменяется, если вы добавляете галочку, которая уже существует.
код:
#!/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')
Ответ 4
Мне нравится ответ Мигеля выше. Работала неплохо. Однако необходимо внести небольшую корректировку. Следующее:
# Get back tick lists
locs=Dticks.keys()
labels=Dticks.values()
необходимо изменить на
# Get back tick lists
locs=list(Dticks.keys())
labels=list(Dticks.values())
поскольку в Python 2.7 +/3, Dict.keys() и Dict.values () возвращают объекты dict_keys и dict_values, которые matplotlib не нравится (по-видимому). Подробнее об этих двух объектах в PEP 3106.