使用Matplotlib与Pandas绘制堆叠时间型水平条形图报错求助
报错原因
你遇到的TypeError: invalid type promotion报错核心有两点:
- pandas内置的
barh堆叠绘图逻辑默认仅支持数值型数据的堆叠,你传入的datetime时间对象属于时间类型,无法直接参与堆叠计算,触发类型错误 - 你代码里存储的是时间点而非每个堆叠段的时长,堆叠水平条形图的每一段需要的是宽度(时长),而非结束时间点,逻辑上也不匹配。
实现方案
绘制设备状态时间线更灵活的方案是直接用matplotlib原生的barh方法,通过left参数控制每个状态段的起始位置,自己管理堆叠逻辑,比pandas封装的绘图接口更适配时间线场景,完整可运行代码如下:
import datetime import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # 构造样本数据:每个设备对应多个状态段,含开始时间、持续时长(秒)、状态 device_status = [ # 设备1的状态段 {"device": "设备1", "start_time": datetime.datetime.now(), "duration": 10, "status": "可用"}, {"device": "设备1", "start_time": datetime.datetime.now() + datetime.timedelta(seconds=10), "duration": 5, "status": "不可用"}, {"device": "设备1", "start_time": datetime.datetime.now() + datetime.timedelta(seconds=15), "duration": 15, "status": "可用"}, # 设备2的状态段 {"device": "设备2", "start_time": datetime.datetime.now(), "duration": 3, "status": "不可用"}, {"device": "设备2", "start_time": datetime.datetime.now() + datetime.timedelta(seconds=3), "duration": 17, "status": "可用"}, {"device": "设备2", "start_time": datetime.datetime.now() + datetime.timedelta(seconds=20), "duration": 10, "status": "不可用"}, ] df = pd.DataFrame(device_status) # 把datetime转成matplotlib可识别的数值时间格式 df["start_num"] = mdates.date2num(df["start_time"]) # 持续时长转成数值时间单位(matplotlib数值时间以天为单位,所以秒数除以86400) df["duration_num"] = df["duration"] / 86400 # 初始化画布 fig, ax = plt.subplots(figsize=(10, 3)) # 设备名映射到y轴坐标 device_y_map = {device: idx for idx, device in enumerate(df["device"].unique())} # 状态和颜色映射:可用绿色,不可用红色 color_map = {"可用": "green", "不可用": "red"} # 逐个绘制每个状态段 for _, row in df.iterrows(): ax.barh( y=device_y_map[row["device"]], width=row["duration_num"], left=row["start_num"], color=color_map[row["status"]], height=0.5 ) # 配置坐标轴显示 ax.set_yticks(list(device_y_map.values())) ax.set_yticklabels(list(device_y_map.keys())) # x轴格式化为可读的时间格式 ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M:%S")) plt.xticks(rotation=45) plt.xlabel("时间") plt.ylabel("设备") plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

