Matplotlib broken_barh按时间分段绘制问题求助(非硬编码宽度)
解决Matplotlib broken_barh按时间分段显示异常的问题
问题说明
需要实现分段水平条形图(broken_barh),按时间自动分段绘制(不硬编码宽度),但当前代码生成的图表显示为连续条形而非分段,且参数输出存在异常。
错误原因
- 未识别连续时间段:原代码仅提取每个
ID Location的首尾时间点,将整个ID的时间区间作为单一段,未区分同一ID的连续时间段(当ID中途切换后再次出现时,会被错误合并成一个大段)。 - 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
相关产品推荐
相关产品推荐

