Python matplotlib - как добавить аннотацию к вертикальной линии - PullRequest
0 голосов
/ 09 января 2020

Я сделал график временного ряда и добавил вертикальную линию. Эта вертикальная линия указывает, что что-то произошло, и я хотел бы добавить аннотацию к этой вертикальной линии. Но я понятия не имею, как это сделать: /

Вот код для отображения данных и вертикальной линии:

Я настроил пример кода, который теперь содержит данные (хотя они как-то странные, но показывают проблему: обозначения на вертикальных линиях должны быть над областью графика, и два текстовых поля теперь перекрываются. Этого перекрытия следует избегать, располагая их по-разному и используя пунктирные линии или что-то, чтобы указать к вертикальной линии, где текст принадлежит

%matplotlib inline
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

data = np.array([['2017-07-01 16:30:00', '2017-07-02 16:30:00', '2017-07-03 16:30:00', '2017-07-04 16:30:00', '2017-07-05 16:30:00', '2017-07-06 16:30:00'],
                [1.4, 1.3, 2, 0.5, 0.002337, 3 ]])

fig2 = plt.figure(figsize=(16,9))

# TRAIN NORTH
ax0 = fig2.add_subplot(111)
ax0.scatter(x=data[0],y=data[1], color='green', marker='.')
#ax0.legend(df.iloc[0,0],loc='best')
#ax0.set_ylim(0,0.006)
# vertical lines when something happened
ax0.axvline('2017-07-02 16:30:00', color='green')
ax0.axvline('2017-07-02 16:30:00', color='green')
ax0.axvline('2017-07-05 16:30:00', color='green')
ax0.text('2017-07-02 16:30:00',0.005,'BigNews1',rotation=90,va='top')
ax0.text('2017-07-02 16:30:00',0.005,'BlaBlaBla2',rotation=90,va='top')
ax0.text('2017-07-05 16:30:00',0.005,'BigNews3',rotation=90,va='top')

Я хотел бы, чтобы что-то похожее было показано на этом рисунке

Они использовали пакет lineid_plot, который можно найти здесь

Однако у этого пакета есть проблемы с форматом даты и времени. Мне очень жаль этот плохой пример кода, показанный здесь, но я действительно новичок и надеюсь, что кто-нибудь может помочь решить мою проблему.

1 Ответ

0 голосов
/ 17 января 2020

Вот код, показывающий аннотацию , аналогичную запрошенным.

Объяснение кода:

  • ymin, ymax = plt.ylim() найти текущие пределы Ось Y, ymax используется для позиционирования текста
  • arrowprops = {'width': 1, 'headwidth': 1, 'headlength': 1, 'shrink':0.05} "стрелка" рисуется от вершины линии к самому тексту. Установка «headwidth» в 1 делает его линией, а не стрелкой. На месте можно нарисовать настоящую стрелку без наложения.
  • ax0.annotate('BigNews1',
    • xy=('2017-07-02 16:30:00', ymax), вершина вертикальной линии
    • xytext=(10, 25), textcoords='offset points', положение текста относительно наверх, измеряется в «точках» (сравните с 12 точками в качестве размера шрифта)
    • rotation=90, va='bottom', ha='center', текст повернут на 90 градусов
    • annotation_clip=False, позволяют писать за пределами поля графика
    • arrowprops=arrowprops) установить свойства "стрелок"

Чего еще не хватает, так это хорошего алгоритма для перемещения по тексту при наложениях.

import matplotlib.pyplot as plt
import numpy as np

data = np.array([['2017-07-01 16:30:00', '2017-07-02 16:30:00', '2017-07-03 16:30:00', '2017-07-04 16:30:00', '2017-07-05 16:30:00', '2017-07-06 16:30:00'],
                [1.4, 1.3, 2, 0.5, 0.002337, 3 ]])

fig2 = plt.figure(figsize=(16,9))
ax0 = fig2.add_subplot(111)
ax0.scatter(x=data[0],y=data[1], color='green', marker='.')
ymin, ymax = plt.ylim()
# vertical lines when something happened
ax0.axvline('2017-07-02 16:30:00', color='green')
ax0.axvline('2017-07-02 16:30:00', color='green')
ax0.axvline('2017-07-05 16:30:00', color='green')

ymin, ymax = plt.ylim()
arrowprops = {'width': 1, 'headwidth': 1, 'headlength': 1, 'shrink':0.05 }
ax0.annotate('BigNews1', xy=('2017-07-02 16:30:00', ymax), xytext=(-10, 25), textcoords='offset points',
             rotation=90, va='bottom', ha='center', annotation_clip=False, arrowprops=arrowprops)
ax0.annotate('BlaBlaBla2', xy=('2017-07-02 16:30:00', ymax), xytext=(10, 25), textcoords='offset points',
             rotation=90, va='bottom', ha='center', annotation_clip=False, arrowprops=arrowprops)
ax0.annotate('BigNews3', xy=('2017-07-05 16:30:00', ymax), xytext=(0, 25), textcoords='offset points',
             rotation=90, va='bottom', ha='center', annotation_clip=False, arrowprops=arrowprops)
plt.tight_layout()
plt.show()

Вот так выглядит верх с этими аннотациями:

top of the plot

...