python - 如何绘制具有多个时间标记词干的时间线?
问题描述
我是 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', ...
笔记:
- 时间线刻度均匀分布
stems1
并且stems2
不一定有相同数量的点,但按顺序排列(如视频时间线)
如果是不同的颜色stems1
,那就更好了。stems2
如果有人能指出我正确的方向,甚至编写一个工作示例,将不胜感激!感谢您的阅读。
编辑:关注@r-beginners 对这篇文章的回答
我有这样的事情:
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()
推荐阅读
- java - 如何为这种情况编写正则表达式?
- node.js - 为什么我在使用 TO_DATE 但在 Oracle SQL 开发人员上工作时收到“ORA-01036:非法变量名/编号”?(使用节点)
- php - 迁移可空字段导致问题
- mysql - SQL查询以查找给定一年的用户参加的最大事件数
- flutter - try/catch 没有捕捉到异常
- java - Hypersill Java解密任务
- python-3.x - Pandas 时间索引 DataFrame 按时差分组
- ios - 使用 Objective-C 中的 Xcode 在 iOS 中以编程方式制作 UI 元素
- perl - 在 Perl 中转换为十六进制值
- c# - 如何在 C# 程序中检测/从慢速 SQL 服务器 I/O 中恢复