创建分段条形图时触发ValueError:数组长度不一致求助
问题分析与解决方案
错误原因
报错ValueError: All arrays must be of the same length是因为data字典中x_values和y_values的长度不匹配:
y_values包含6个元组,对应6条条形图的位置与高度- 原代码中
x_values按5个类别收集数据,最终长度为5,和y_values的6无法匹配
同时原代码逻辑颠倒:应该是每条条形图对应5个类别分段,而非5个类别对应6条条形。
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt from matplotlib.patches import Patch import tkinter as tk from tkinter import messagebox # 定义数据结构:6条条形图,对应y轴的6个Jobs data = { 'x_values': [], 'y_values': [(6.0, 2), (8.5, 2), (12.5, 2), (15.0, 2), (19.0, 2), (21.5, 2)] } # 颜色与类别定义 colors = ('tab:red', 'tab:orange', 'tab:purple', 'tab:blue', 'tab:green') categories = ('Category 1', 'Category 2', 'Category 3', 'Category 4', 'Category 5') # 6条条形对应的标签 job_labels = ['#3-actual', '#3-budget', '#2-actual', '#2-budget', '#1-actual', '#1-budget'] # 获取用户输入的分段数据 def get_x_values(): global data x_values = [] try: # 遍历6条条形图 for i in range(len(job_labels)): segment_list = [] # 每条条形对应5个类别分段 for j in range(len(categories)): input_str = x_values_entry[i][j].get().strip() if not input_str: raise ValueError(f"第{i+1}条条形的{categories[j]}输入不能为空") start, duration = input_str.split(',') start = int(start) duration = int(duration) # 验证时长为正整数 if duration <=0: raise ValueError(f"{categories[j]}的时长必须是正整数") segment_list.append((start, duration)) # 验证当前条形的分段起始值递增,避免重叠 sorted_starts = sorted([seg[0] for seg in segment_list]) if sorted_starts != [seg[0] for seg in segment_list]: messagebox.showwarning("输入警告", f"第{i+1}条条形的分段起始值未按递增顺序输入,可能导致重叠") x_values.append(segment_list) data['x_values'] = x_values root.destroy() except ValueError as e: messagebox.showerror("输入错误", str(e)) # 创建GUI root = tk.Tk() root.title("分段条形图数据输入") # 布置输入网格:6行(对应6条条形),每行5个输入框(对应5个类别) x_values_entry = [] for i in range(len(job_labels)): label = tk.Label(root, text=job_labels[i]) label.grid(row=i, column=0, padx=5, pady=5) entries = [] for j in range(len(categories)): entry = tk.Entry(root, width=12) entry.grid(row=i, column=j+1, padx=3, pady=5) # 示例提示 entry.insert(0, "0,1") entries.append(entry) x_values_entry.append(entries) # 提交按钮 submit_button = tk.Button(root, text='提交数据', command=get_x_values) submit_button.grid(row=len(job_labels), columnspan=len(categories)+1, pady=10) # 运行GUI root.mainloop() # 为DataFrame添加颜色数据:每条条形对应5个颜色 data['facecolors'] = [list(colors) for _ in range(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.02)) # 自定义坐标轴 ax.set_xlabel('Days') ax.set_ylabel('Jobs') ax.set_yticks([7, 9.5, 13.5, 16, 20, 22.5], labels=job_labels) title = ax.set_title('Tasks and Crew-Days') title.set_position([0.5, 1.0]) ax.set_ylim(5, 26) ax.grid(True) plt.tight_layout() plt.show()
关键修改说明
- 数据结构调整:将
x_values改为收集6组数据(对应6条条形),每组包含5个分段,确保和y_values长度一致 - GUI布局优化:按6条条形(Jobs标签)布置输入行,每行对应5个类别分段输入,符合需求逻辑
- 输入验证增强:添加空值检查、整数格式验证、时长正整数验证,以及分段起始值递增提示,避免数据错误
- 颜色赋值修正:为每条条形生成对应的5个颜色列表,确保分段颜色与类别一一匹配
- 用户体验优化:添加输入框示例提示、错误弹窗警告,提升使用友好性
内容的提问来源于stack exchange,提问作者gerald
相关产品推荐
相关产品推荐

