分段条形图彩色类别分配异常问题求助
分段条形图最后一个绿色部分异常延伸的问题排查与修复
问题根源
- 输入分段重叠:你提供的输入示例中,分段存在重叠情况。比如第三个分段
20,29(结束于49)与第四个30,39(结束于69)重叠,第四个又和第五个40,49(结束于89)重叠。最后一个绿色分段会覆盖前面的部分,视觉上就会显得“异常延伸”。 - 代码冗余赋值:原代码中对
data['facecolors']和data['categories']的循环赋值完全冗余,虽然不影响功能,但写法不规范。 - 缺少输入验证:没有对用户输入的合法性和分段顺序做校验,容易导致重叠、格式错误等问题。
解决方案
- 修正输入逻辑:确保每个分段的起始值等于前一个分段的
起始值+时长,比如输入1,9(结束10)、10,9(结束19)、20,9(结束29)、30,9(结束39)、40,9(结束49),保证分段完全连续不重叠。 - 优化代码逻辑:移除冗余的循环赋值,添加输入验证机制,避免非法输入导致的图表异常。
修改后的完整代码
import pandas as pd import matplotlib.pyplot as plt from matplotlib.patches import Patch import tkinter as tk from tkinter import messagebox # 初始化数据字典 data = { 'x_values': [], 'y_values': [(6.0, 2), (8.5, 2), (12.5, 2), (15.0, 2), (19.0, 2)] } # 定义颜色和分类 colors = ('tab:red', 'tab:orange', 'tab:purple', 'tab:blue', 'tab:green') categories = ('Cat1', 'Cat2', 'Cat3', 'Cat4', 'Cat5') jobs = ('Job1', 'Job2', 'Job3', 'Job4', 'Job5') # 验证输入分段是否合法(无重叠、时长为正) def validate_input(values_list): prev_end = 0 for idx, (start, duration) in enumerate(values_list): if start < prev_end: return f"第{idx+1}个分段起始值{start}小于前一个分段的结束值{prev_end},存在重叠" if duration <= 0: return f"第{idx+1}个分段时长{duration}必须大于0" prev_end = start + duration return None # 获取用户输入并校验 def get_x_values(): global data x_values = [] for i in range(len(jobs)): values_list = [] for j in range(len(categories)): input_str = x_values_entry[i][j].get().strip() if not input_str: messagebox.showerror("输入错误", f"{jobs[i]}的{categories[j]}分段不能为空") return try: x, y = input_str.split(',') start = int(x.strip()) duration = int(y.strip()) values_list.append((start, duration)) except ValueError: messagebox.showerror("输入错误", f"{jobs[i]}的{categories[j]}分段必须是逗号分隔的两个整数") return # 校验当前任务的分段是否合法 error_msg = validate_input(values_list) if error_msg: messagebox.showerror("输入错误", f"{jobs[i]}的分段存在问题:{error_msg}") return x_values.append(values_list) data['x_values'] = x_values root.destroy() # 创建GUI界面 root = tk.Tk() root.title("输入分段数据") x_values_entry = [] for i in range(len(jobs)): row = [] for j in range(len(categories)): if i == 0: label = tk.Label(root, text=categories[j]) label.grid(row=i, column=j+1, padx=5, pady=5) if j == 0: label = tk.Label(root, text=jobs[i]) label.grid(row=i+1, column=j, padx=5, pady=5) entry = tk.Entry(root, width=10) # 设置默认示例输入 entry.insert(0, f"{10*j+1},9") entry.grid(row=i+1, column=j+1, padx=5, pady=5) row.append(entry) x_values_entry.append(row) # 提交按钮 submit_button = tk.Button(root, text='提交', command=get_x_values) submit_button.grid(row=len(jobs)+1, columnspan=len(categories)+1, pady=10) root.mainloop() # 重新定义分类名称 categories = ('Category 1', 'Category 2', 'Category 3', 'Category 4', 'Category 5') # 直接赋值颜色和分类,移除冗余循环 data['facecolors'] = [colors] * len(data['x_values']) data['categories'] = [categories] * len(data['x_values']) # 创建DataFrame df = pd.DataFrame(data) # 绘制图表 fig, ax = plt.subplots(figsize=(10,6)) for i, row in df.iterrows(): ax.broken_barh(row['x_values'], row['y_values'], facecolors=row['facecolors']) # 创建图例 legend_entries = [Patch(facecolor=color, edgecolor='black', label=category) for color, category in zip(colors, categories)] ax.legend(handles=legend_entries, loc='upper right', ncol=5, bbox_to_anchor=(1.0, 1.00)) # 自定义图表样式 ax.set_xlabel('Days') ax.set_ylabel('Jobs') ax.set_yticks([7, 9.5, 13.5, 16, 20], labels=['Job1', 'Job2', 'Job3','Job4', 'Job5']) title = ax.set_title('Tasks and Crew-Days') title.set_position([0.5, 1.0]) ax.set_ylim(5, 26) ax.grid(True) plt.show()
关键修改点
- 新增输入验证,自动检查分段重叠、非法格式、负时长等问题
- GUI中添加默认示例输入,引导用户输入正确格式
- 移除冗余的循环赋值逻辑,简化代码
- 增加错误弹窗提示,方便用户快速定位输入问题
内容的提问来源于stack exchange,提问作者gerald
相关产品推荐
相关产品推荐

