【问题标题】:Create a temporal plot of events with dashed lines with matplotlib & pandas使用 matplotlib 和 pandas 用虚线创建事件的时间图
【发布时间】:2019-02-13 00:15:11
【问题描述】:

我正在尝试创建一个虚线图,代表我的每个哈希的事件长度。我的数据框如下:

                            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

类似于这里的答案:Change spacing of dashes in dashed line in matplotlib 其中散列在 y 轴上,在 x 轴上有时间间隔,事件类型用颜色编码,如果在该时间间隔内没有事件,则用空格分隔。

这是我迄今为止尝试过的,但它不起作用:

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

请看下面的例子

【问题讨论】:

  • hmm,你能上传一张你想用matplotlib构建的手绘图表吗
  • matplotlib 中从点 (x1,y1) 到 (x2,y2) 的线定义为plt.plot([x1,x2],[y1,y2])
  • @ImportanceOfBeingErnest 这很有帮助,而且似乎朝着正确的方向发展。您将如何自动计算每个散列的每个事件的每个开始/停止的那些?
  • 我认为它们已经存在于数据框中。 df["start"][4] 是开始列中的第五个数字。但是,您需要将 00:00:01:500 转换为可以绘制的某个数字。
  • @HaleemurAli 我编辑了问题 - 检查图片

标签: python pandas matplotlib


【解决方案1】:

首先我想说:我与您的请求的第一个关联是 matplotlib 的 broken_barh 函数。但到目前为止,我无法弄清楚如何绘制时间增量,因为这在那里是必要的。你的情节也可以用plot 完成,所以我有一些带有if False: (attempt with plt.broken_barh) else (plt.plot-version) 结构的代码。看看你自己。
一旦我知道如何在 matplotlib 中绘制 timedeltas,我将尝试更新字面上的 broken 部分......

这是我希望可以帮助你的代码:

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 的结果:

【讨论】:

  • 我认为这是正确的方向。我目前只能获得一个要绘制的哈希,然后是 ax.plot([a, b], i*np.ones(2)+k/10, clrs[k], lw=15, label='_' if i>0 or n>0 else '' + e) 行的列表索引超出范围,我无法弄清楚导致问题的原因。您介意在上面的代码中评论每行引用的内容吗?我基本上可以跟随,但在第二个 for 循环中有点迷失。
  • 那里唯一的列表是clrs,它只有两个条目,因为您的示例没有更多条目。所以我假设你现在用两个以上的事件测试代码?出于测试目的,您可以完全删除 clrs-kwarg,但要使绘图看起来正确,clrs 需要具有与数据中的事件一样多的颜色条目。 - 根据您的要求:我会尽快添加更多的 cmets...
  • 有没有办法将 clrs 列表更改为颜色图,类似于:pandas.pydata.org/pandas-docs/version/0.15.0/…
  • 当然可以。与此同时,我认为交换分组会更好,即先按事件分组,然后按哈希分组。这会导致自动应用颜色循环(在第一个哈希处,然后可以为所有其他哈希重用),因此您不必担心事先创建一些东西。我会朝那个方向更新代码,如果这对你来说没问题...补充:clrs 最初的目的只是为了满足你的手绘颜色。
  • 我尝试按事件分组然后散列,但这使 y 轴成为事件而不是散列。否则,删除 clrs 列表有效。现在我只需要弄清楚如何最好地让显示器工作 - 我正在尝试将时间戳旋转 45 以使其可读。
猜你喜欢
  • 2018-08-13
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 2017-10-22
  • 2017-08-26
  • 1970-01-01
  • 2019-01-01
  • 2014-07-27
相关资源
最近更新 更多