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

Matplotlib broken_barh按时间分段绘制问题求助(非硬编码宽度)

解决Matplotlib broken_barh按时间分段显示异常的问题

问题说明

需要实现分段水平条形图(broken_barh),按时间自动分段绘制(不硬编码宽度),但当前代码生成的图表显示为连续条形而非分段,且参数输出存在异常。

错误原因

  1. 未识别连续时间段:原代码仅提取每个ID Location的首尾时间点,将整个ID的时间区间作为单一段,未区分同一ID的连续时间段(当ID中途切换后再次出现时,会被错误合并成一个大段)。
  2. broken_barh参数错误:broken_barh的分段格式应为[(起始值, 持续时长)],原代码误将结束值作为第二个参数,导致条形长度计算错误。

修正后的代码

import numpy as np
import matplotlib.pylab as plt
import pandas as pd

def make_broken_barhs(df):
    barh_list = []
    id_loc_list = []
    
    # 遍历数据,识别连续相同ID的时间段
    current_id = df['ID Location'].iloc[0]
    start_time = df.index[0]
    
    for idx, row in df.iloc[1:].iterrows():
        if row['ID Location'] != current_id:
            # 计算当前连续段的起始时间和持续时长
            end_time = df.index[df.index < idx].max()
            duration = end_time - start_time
            barh_list.append([(start_time, duration)])
            id_loc_list.append(current_id)
            
            # 更新当前ID和起始时间
            current_id = row['ID Location']
            start_time = idx
    
    # 处理最后一段
    duration = df.index[-1] - start_time
    barh_list.append([(start_time, duration)])
    id_loc_list.append(current_id)
    
    return barh_list, id_loc_list

def plot_df(df):
    barh_segments, loc_ids = make_broken_barhs(df)
    
    # 创建适合时间轴的绘图对象
    fig, ax = plt.subplots()
    # 设置x轴为时间格式
    ax.set_xlim(df.index.min(), df.index.max())
    ax.xaxis_date()
    plt.xticks(rotation=45)
    
    # 绘制分段条形,统一在一行(y=0,高度0.5)
    color_map = {18:'#FF6B6B',19:'#4ECDC4',20:'#45B7D1',21:'#96CEB4',22:'#FFEAA7',23:'#DDA0DD',24:'#F4A460'}
    for segments, loc in zip(barh_segments, loc_ids):
        ax.broken_barh(segments, 
                       (0, 0.5), 
                       facecolor=color_map[loc],
                       label=f'ID {loc}')
    
    ax.set_yticks([0.25])
    ax.set_yticklabels(['时间分段'])
    ax.legend(loc='upper right', bbox_to_anchor=(1.1, 1))
    plt.tight_layout()
    plt.show()

# 生成测试数据
idx = pd.date_range('2023-01-18 06:00:00', '2023-01-19 06:00:00', freq='h')
df = pd.DataFrame({'ID Location': np.random.randint(low=18, high=25, size=(len(idx),))}, 
                  index=idx)

plot_df(df)

关键改动说明

  • 识别连续时间段:遍历数据,当ID Location发生变化时,记录上一段的起始和结束时间,计算持续时长,实现按连续相同ID分段。
  • 修正broken_barh参数:直接使用时间戳和Timedelta作为分段参数,避免ordinal转换的混淆,同时让x轴自动适配时间格式。
  • 优化可视化:为不同ID分配专属颜色,添加旋转时间标签、图例,提升图表可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:45:37