如何绘制具有多个时间标记的时间线?

How to plot timeline with multiple time-marker stems?

我是 matplotlib 的新手,正在尝试绘制一些非常困难的东西。

我想绘制类似的东西(取自matplotlib docs):

除此之外,我希望时间轴(x 轴)和主干具有时间标签,例如:

timeline = ['0:01:00', '0:02:00', '0:03:00', '0:04:00', ...]
stems1 = ['0:01:45', '0:03:55', '0:04:22', ...]
stems2 = ['0:02:21', '0:06:54', ...

备注:

如果stems1stems2是不同的颜色就更好了

如果有人能给我指出正确的方向,或者编写一个工作示例,我将不胜感激!感谢阅读。


编辑: 按照@r-初学者对 this post

的回答

我有这样的东西:

for time, level, label, va in zip(timeline, levels, labels, verticalalignments):
        ax.annotate(label, xy=(time, level), xytext=(15, np.sign(level)*15),
                    textcoords="offset points",
                    verticalalignment=va,
                    horizontalalignment="right",
                    color='blue')

    for time, level, pred, va in zip(timeline, levels, preds, verticalalignments):
        ax.annotate(pred, xy=(time, level), xytext=(15, np.sign(level)*15),
                    textcoords="offset points",
                    verticalalignment=va,
                    horizontalalignment="right",
                    color='green')

问题是图表重叠,主干颜色均为红色,主干与时间线不对齐。


编辑 2: 使用@r-beginners 代码,我尝试了 2 个新词干,其中 stem1 没有被完全绘制:

stem1 = ['0:08:08', '0:08:52', '0:09:42', '0:10:20', '0:10:55', '0:11:24', '0:12:31', '0:13:07', '0:13:45', '0:14:16', '0:14:49', '0:15:20', '0:15:51', '0:16:21', '0:16:53', '0:17:28', '0:19:01', '0:19:22', '0:20:19', '0:20:48', '0:21:19', '0:22:05', '0:23:06', '0:23:34', '0:24:03', '0:24:30', '0:24:51', '0:25:18', '0:25:54', '0:26:25', '0:27:07', '0:28:05', '0:29:04', '0:29:30', '0:30:34', '0:32:57', '0:33:28', '0:33:57', '0:34:35', '0:35:01', '0:35:41', '0:36:06', '0:36:30', '0:37:01', '0:37:33', '0:38:06', '0:38:40', '0:39:21', '0:40:02', '0:40:22', '0:40:42', '0:41:32', '0:41:56', '0:43:20', '0:43:39', '0:44:02', '0:44:26', '0:45:04', '0:45:32', '0:46:02', '0:47:00', '0:47:42', '0:48:05', '0:48:35', '0:49:02', '0:49:25', '0:49:56', '0:50:43', '0:51:25', '0:51:43', '0:52:18', '0:52:49', '0:53:08']

stem2 = ['0:09:49', '0:10:24', '0:14:27', '0:24:31', '0:26:03']

之后的代码:

# Create figure
    fig, ax = plt.subplots(figsize=(100, 10), constrained_layout=True)
    ax.set(title='TEST')

    # Stem values
    names = [e for row in zip(stem1, stem2) for e in row]

    # Timeline
    timeline = [datetime.datetime.strptime(n, '%H:%M:%S') for n in names]

    # Stem levels
    levels = np.tile([-5, 5, -3, 3, -1, 1], int(np.ceil(len(names)/6)))[:len(names)]

    # Stems
    ax.vlines(timeline, 0, levels, color='tab:red')

    # Plot timeline
    ax.plot(timeline, np.zeros_like(timeline), "-o", color="k", markerfacecolor="w")

    # Plot GT labels and predictions
    for time, level, name in zip(timeline, levels, names):
        ax.annotate(name, xy=(time, level),
                    xytext=(15, np.sign(level)*3),
                    textcoords='offset points',
                    horizontalalignment='right',
                    verticalalignment='bottom' if level > 0 else 'top',
                    color='green' if level > 0 else 'blue')

    # De-clutter axes
    ax.yaxis.set_visible(False)
    ax.spines[["left", "top", "right"]].set_visible(False)

    # ...
    minutes = mdates.MinuteLocator(interval=1)
    minutes_fmt = mdates.DateFormatter('%M:%S')
    ax.xaxis.set_major_locator(minutes)
    ax.xaxis.set_major_formatter(minutes_fmt)

    # Rotate x-ticks
    plt.setp(ax.get_xticklabels(), rotation=30, ha="right")

    # Save figure
    plt.savefig('test.png', bbox_inches='tight')

数据只有部分可用,所以我适当地创建了它。我已经参考你提到的官方例子解决了你的问题。对于重叠的字符串,创建一个正负放置高度列表,并绘制一条红色垂直线。将词干信息转化为时间序列信息,画出时间线。在注解循环过程中,通过判断放置高度值进行放置和颜色区分。 x轴的时间序列表示由MinuteLocator设置确定时间格式。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib.dates as mdates
from datetime import datetime

fig, ax = plt.subplots(figsize=(16, 4), constrained_layout=True)
ax.set(title="Time line demo ")

stem1 = ['0:08:08', '0:08:52', '0:09:42', '0:10:20', '0:10:55', '0:11:24', '0:12:31', '0:13:07', '0:13:45', '0:14:16', '0:14:49', '0:15:20', '0:15:51', '0:16:21', '0:16:53', '0:17:28', '0:19:01', '0:19:22', '0:20:19', '0:20:48', '0:21:19', '0:22:05', '0:23:06', '0:23:34', '0:24:03', '0:24:30', '0:24:51', '0:25:18', '0:25:54', '0:26:25', '0:27:07', '0:28:05', '0:29:04', '0:29:30', '0:30:34', '0:32:57', '0:33:28', '0:33:57', '0:34:35', '0:35:01', '0:35:41', '0:36:06', '0:36:30', '0:37:01', '0:37:33', '0:38:06', '0:38:40', '0:39:21', '0:40:02', '0:40:22', '0:40:42', '0:41:32', '0:41:56', '0:43:20', '0:43:39', '0:44:02', '0:44:26', '0:45:04', '0:45:32', '0:46:02', '0:47:00', '0:47:42', '0:48:05', '0:48:35', '0:49:02', '0:49:25', '0:49:56', '0:50:43', '0:51:25', '0:51:43', '0:52:18', '0:52:49', '0:53:08']
stem2 = ['0:09:49', '0:10:24', '0:14:27', '0:24:31', '0:26:03']

stems = stem1 + stem2
timelines = sorted([datetime.strptime(s, '%H:%M:%S') for s in stem])
labels = [datetime.strftime(t, '%H:%M:%S') for t in timelines]
levels = np.tile([-7, 7, -5, 5, -3, 3, -1, 1], int(np.ceil(len(timelines)/8)))[:len(timelines)]

ax.vlines(timelines, 0, levels, color='tab:red')
ax.plot(timelines, np.zeros_like(timelines), "-o", color="k", markerfacecolor="w")

for t, l, b in zip(timelines, levels, labels):
    if datetime.strftime(t, '%H:%M:%S')[1:] in stem2:
        color = 'blue'
    else:
        color = 'green'
    ax.annotate(b, xy=(t, l),
                xytext=(22, np.sign(l)*3), textcoords='offset points',
                horizontalalignment='right',
                verticalalignment='bottom' if l > 0 else 'top',
                color=color
               )
    
ax.yaxis.set_visible(False)
ax.spines[["left", "top", "right"]].set_visible(False)
ax.spines['bottom'].set_position(('data', -8))

minutes = mdates.MinuteLocator(interval=1)
minutes_fmt = mdates.DateFormatter('%M:%S')
ax.xaxis.set_major_locator(minutes)
ax.xaxis.set_major_formatter(minutes_fmt)

plt.setp(ax.get_xticklabels(), rotation=90, ha='center')

plt.show()