You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Matplotlib绘制RTTM时序事件的持续时间序列图?

问题描述

我有如下Pandas DataFrame:

0 music 0.00 9.02 
1 female 9.02 152.70 
2 music 152.70 155.12 
3 female 155.12 206.82 
4 noEnergy 206.82 208.10 

该数据包含ID、TYPE、START、END字段,所有事件按顺序排列且无重叠。我的目标是绘制一张事件持续时间序列图表,让music类型在0-9.02区间连续展示,female类型在9.02-152.70区间连续展示,以此类推。

我尝试了两种方法都不符合需求:

  1. 散点图仅展示起始时间点:
# Read data from RTTM files into data frames
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df1 = pd.read_csv('file.rttm', sep=' ', names=['type', 'start', 'end'])
df1.plot(x='start', y='type', kind='scatter', rot='vertical')
plt.show()
  1. 折线图仍不符合需求:
df1['duration'] = (df1['end'] - df1['start'])
plt.plot(df1['start'], df1['type'])
plt.show()

请问正确的可视化方法是什么?

解决方案

你需要的是时序分段的类别条形图(类似时间轴事件图),下面是两种可行的实现方案:

方案一:使用matplotlib的broken_barh(推荐)

broken_barh是matplotlib专门用于绘制水平分段条形的方法,完美匹配你的需求:

import pandas as pd
import matplotlib.pyplot as plt

# 读取数据,补充ID列命名
df1 = pd.read_csv('file.rttm', sep=' ', names=['id', 'type', 'start', 'end'])
# 计算每个事件的持续时间
df1['duration'] = df1['end'] - df1['start']

# 给每个事件类型分配唯一的y轴位置,避免重叠
type_mapping = {t:i for i,t in enumerate(df1['type'].unique())}
df1['y_pos'] = df1['type'].map(type_mapping)

plt.figure(figsize=(12,4))
# 遍历每个事件绘制分段条形
for idx, row in df1.iterrows():
    # 仅在第一个出现的类别添加图例,避免重复
    plt.broken_barh([(row['start'], row['duration'])], (row['y_pos']-0.4, 0.8), 
                    label=row['type'] if idx==0 else "")

# 设置坐标轴和图例
plt.yticks(list(type_mapping.values()), list(type_mapping.keys()))
plt.xlabel('时间')
plt.ylabel('事件类型')
plt.title('事件时序持续图')
plt.legend()
plt.tight_layout()
plt.show()

方案二:转换数据为连续点绘制折线+填充

如果想用折线图形式实现连续展示,可以将每个事件的start和end拆分为两个点,再用steps-post绘制连续折线:

import pandas as pd
import matplotlib.pyplot as plt

df1 = pd.read_csv('file.rttm', sep=' ', names=['id', 'type', 'start', 'end'])
# 转换数据:每个事件拆成(start, type)和(end, type)两个点
plot_data = []
for _, row in df1.iterrows():
    plot_data.append({'time': row['start'], 'type': row['type']})
    plot_data.append({'time': row['end'], 'type': row['type']})
plot_df = pd.DataFrame(plot_data)

# 将类别映射为数值,用于y轴绘制
type_mapping = {t:i for i,t in enumerate(df1['type'].unique())}
plot_df['y_val'] = plot_df['type'].map(type_mapping)

plt.figure(figsize=(12,4))
# 使用steps-post确保折线在时间区间内保持水平
plt.plot(plot_df['time'], plot_df['y_val'], drawstyle='steps-post', linewidth=3)
# 可选:给每个类别区间添加填充色,增强可读性
for t in type_mapping:
    subset = plot_df[plot_df['type']==t]
    plt.fill_between(subset['time'], type_mapping[t]-0.3, type_mapping[t]+0.3, alpha=0.2)

plt.yticks(list(type_mapping.values()), list(type_mapping.keys()))
plt.xlabel('时间')
plt.ylabel('事件类型')
plt.title('事件时序持续图')
plt.tight_layout()
plt.show()

这两种方法都能实现你要的效果:每个事件类型在对应时间区间内连续展示,不会仅显示单个时间点。

内容的提问来源于stack exchange,提问作者user3925023

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:45:25