求助:基于Python自定义类数据绘制甘特图
基于Python类结构数据绘制甘特图
你可以通过以下步骤实现需求,核心是先将嵌套的类结构数据扁平化,再使用Matplotlib的barh方法绘制甘特图:
1. 补全类定义(添加构造方法)
原类仅有类型注解,无法直接创建实例,需补充__init__方法:
from typing import List, Any import matplotlib.pyplot as plt # 定义未分配标记(与你代码中的UNASSIGNED_FLAG一致) UNASSIGNED_FLAG = -1 class Stage: def __init__(self, id: int): self.id = id self.production_equipment: List[ProductionEquipment] | None = [] class ProductionEquipment: def __init__(self, id: int, norm_mw: Any, stage: int): self.id = id self.norm_mw = norm_mw self.stage = stage self.production_tasks: List[ProductionTask] | None = [] class ProductionTask: def __init__(self, id: int, processingtime: int, duration: float, done: bool): self.id = id self.processingtime = processingtime self.duration = duration self.done = done self.start_time: int = UNASSIGNED_FLAG self.end_time: int = UNASSIGNED_FLAG self.production_equipment: Any = UNASSIGNED_FLAG self.stage: Any = UNASSIGNED_FLAG
2. 生成模拟数据(匹配你的3阶段2设备场景)
如果已有真实数据,可跳过此步骤,直接使用你的业务数据:
# 创建3个阶段,每个阶段2台设备,每台设备分配2个已排程任务 stages = [] for stage_id in range(1, 4): stage = Stage(stage_id) for eq_id in range(1, 3): equipment = ProductionEquipment(eq_id, 100, stage_id) # 任务1 task1 = ProductionTask(id=eq_id*10+1, processingtime=5, duration=12.0, done=False) task1.start_time = 10 + (stage_id-1)*20 + (eq_id-1)*5 task1.end_time = task1.start_time + int(task1.duration) task1.production_equipment = equipment task1.stage = stage_id # 任务2 task2 = ProductionTask(id=eq_id*10+2, processingtime=5, duration=18.0, done=False) task2.start_time = task1.end_time + 3 task2.end_time = task2.start_time + int(task2.duration) task2.production_equipment = equipment task2.stage = stage_id equipment.production_tasks.extend([task1, task2]) stage.production_equipment.append(equipment) stages.append(stage)
3. 扁平化数据(提取绘图所需字段)
将嵌套的Stage->ProductionEquipment->ProductionTask结构展开,提取设备标签、任务起始时间、任务时长:
equipment_labels = [] task_starts = [] task_durations = [] task_colors = [] # 用于区分不同任务的颜色池 color_list = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b'] for stage in stages: for equipment in stage.production_equipment: # 生成易识别的设备标签,如"阶段1-设备1" eq_label = f"阶段{stage.id}-设备{equipment.id}" equipment_labels.append(eq_label) # 仅处理已分配的任务(排除start_time为UNASSIGNED_FLAG的任务) for idx, task in enumerate(equipment.production_tasks): if task.start_time != UNASSIGNED_FLAG: task_starts.append(task.start_time) task_durations.append(task.duration) task_colors.append(color_list[idx % len(color_list)])
4. 绘制甘特图
使用barh方法绘制,设置X轴范围为0-96时间步:
fig, ax = plt.subplots(figsize=(12, 6)) # barh参数说明:y轴位置为设备索引,宽度为任务时长,左边界为任务起始时间 y_positions = range(len(equipment_labels)) ax.barh(y_positions, task_durations, left=task_starts, color=task_colors, edgecolor='black') # 设置轴标签与范围 ax.set_yticks(y_positions) ax.set_yticklabels(equipment_labels) ax.set_xlim(0, 96) ax.set_xlabel("时间步") ax.set_ylabel("设备") ax.set_title("设备生产任务甘特图") # 添加垂直网格线,便于查看时间节点 ax.grid(True, axis='x', linestyle='--', alpha=0.7) # 调整布局,避免标签被截断 plt.tight_layout() plt.show()
关键注意点
- 若使用真实数据,需确保
ProductionTask的start_time和end_time已正确赋值(不是UNASSIGNED_FLAG) barh的left参数是实现甘特图的核心,它指定了每个任务的起始位置,而非默认的从Y轴开始
内容的提问来源于stack exchange,提问作者Margi Shah
相关产品推荐
相关产品推荐

