Создайте временной график событий с пунктирными линиями с помощью matplotlib & pandas - PullRequest
0 голосов
/ 07 сентября 2018

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

                            hash    event        start          end
0174FAA018E7FAE1E84469ADC34EF666 baseball 00:00:00:000 00:00:00:500
0174FAA018E7FAE1E84469ADC34EF666 baseball 00:00:01:000 00:00:01:500
0174FAA018E7FAE1E84469ADC34EF666 cat      00:00:01:500 00:00:02:500
AF4BB75F98579B8C9F95EABEC1BDD988 baseball 00:00:01:000 00:00:01:500
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:01:500 00:00:02:500
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:03:200 00:00:05:250
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:03:000 00:00:04:350

что-то похожее на ответ здесь: Изменение расстояния между штрихами в пунктирной линии в matplotlib где хеши находятся на оси y, а на оси x имеются временные интервалы с цветовыми кодировками типов событий и разделены пробелами, если для этого временного интервала нет событий.

это то, что я пробовал до сих пор, но это не работает:

fig,ax = plt.subplots()
ax.plot([0, df.end], [df.hash], linestyle='--', dashes=(5, 5)) 

см. Ниже, например

garbage hand-drawn graph

1 Ответ

0 голосов
/ 08 сентября 2018

Сначала я хотел бы сказать: моей первой ассоциацией с вашим запросом была функция broken_barh в matplotlib. Но до сих пор я не мог понять, как построить таймделты, поскольку это было бы необходимо там. Ваш сюжет может быть выполнен и с plot, поэтому у меня есть некоторый код со структурой if False: (attempt with plt.broken_barh) else (plt.plot-version). Смотри сам.
Я постараюсь обновить буквально неработающую часть, как только у меня появится идея, как построить timedeltas в matplotlib ...

Вот код, который, я надеюсь, может вам помочь:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from io import StringIO


def brk_str(s):       # just for nicer labeling with such long hashes
    return '\n'.join([s[8*i:8*(i+1)] for i in range(4)])


s = '''                            hash    event        start          end
0174FAA018E7FAE1E84469ADC34EF666 baseball 00:00:00:000 00:00:00:500
0174FAA018E7FAE1E84469ADC34EF666 baseball 00:00:01:000 00:00:01:500
0174FAA018E7FAE1E84469ADC34EF666 cat      00:00:01:500 00:00:02:500
AF4BB75F98579B8C9F95EABEC1BDD988 baseball 00:00:01:000 00:00:01:500
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:01:500 00:00:02:500
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:03:200 00:00:05:250
AF4BB75F98579B8C9F95EABEC1BDD988 cat      00:00:03:000 00:00:04:350'''

df = pd.read_table(StringIO(s), sep='\s+')

df['start'] = pd.to_datetime(df['start'], format='%H:%M:%S:%f')
df['end'] = pd.to_datetime(df['end'], format='%H:%M:%S:%f')

df['dur'] = (df['end'] - df['start'])   # this is only needed in case of broken_barh would work...

e_grpd = df.groupby('event')

fig, ax = plt.subplots()

for i, (e, ev) in enumerate(e_grpd):   # iterate over all events, providing a counter i, the name of every event e and its data ev
    last_color = None    # setting color value to None which means automatically cycle to another color
    for k, (h, hv)in enumerate(ev.groupby('hash')):   # iterate over all hashes, providing a counter k, every hash h and its data hv
        if False:   # desperately not deleting this as broken_barh would save the innermost loop and would generally fit better I think...
            pass
            #ax.broken_barh(ev[['start', 'dur']].T, np.array([i*np.ones(len(ev))+k/10, .1*np.ones(len(ev))]).T)
        else:
            for n, (a, b) in enumerate(zip(hv.start, hv.end)):   # iterate over every single event per hash, providing a counter n and start and stop time a and b
                p = ax.plot([a, b], k*np.ones(2)+i/10, color=last_color, lw=15, label='_' if k>0 or n>0 else '' + e)
                last_color = p[0].get_c()    # setting color value to the last one used to prevent color cycling


ax.set_yticks(range(len(df.groupby('hash').groups)))
ax.set_yticklabels(map(brk_str, df.groupby('hash').groups))
ax.legend(ncol=2, bbox_to_anchor=[0, 0, 1, 1.1], loc=9, edgecolor='w')
plt.tight_layout()

Результат с plt.plot:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...