Matplotlib中y_pos的作用是什么?为何不能直接用fullnames替代?
嘿,我来帮你理清这个y_pos的问题,顺便揪出你代码里的小bug~
首先得说,你当前代码里的y_pos用法其实有问题——它单独排序了姓名,但没同步排序分数,这会导致分数和姓名完全不匹配!先拆解清楚:
你代码里的核心问题
你写了y_pos = sorted(fullnames),然后用plt.bar(y_pos, scores),最后又加了plt.xticks(y_pos, fullnames):
y_pos是排序后的姓名列表,但scores还是数据库查询出来的原始顺序,这意味着第一个柱子对应的是排序后的第一个姓名,但分数却是原始列表的第一个值,完全对不上号。plt.xticks(y_pos, fullnames)更是错上加错:Matplotlib会把y_pos里每个姓名对应的x轴位置(比如第一个姓名对应位置0),替换成fullnames里同索引的原始姓名,直接导致标签和柱子错位。
为什么不能直接用fullnames替代y_pos?
如果直接把y_pos换成fullnames,柱子会按数据库查询的原始姓名顺序排列,而不是你想要的排序后的顺序。但更关键的是,你当前的plt.xticks逻辑完全不匹配,会让整个图表的对应关系混乱。
修正后的正确写法
要解决这个问题,你需要把姓名和分数配对后一起排序,确保两者顺序始终对应:
def CreateScoreBarChart(subject): # 获取对应学科的姓名和分数 GetScoresSQL="""SELECT firstname,secondname,score FROM students WHERE subject=%s""" mycursor.execute(GetScoresSQL,(subject,)) myresults = mycursor.fetchall() # 把姓名和分数配对成元组,方便后续排序 student_data = [] for person in myresults: fullname = f"{person[0]} {person[1]}" student_data.append( (fullname, person[2]) ) # 按姓名排序(如果想按分数排序,把key改成lambda x: x[1]即可) sorted_students = sorted(student_data, key=lambda x: x[0]) sorted_names = [item[0] for item in sorted_students] sorted_scores = [item[1] for item in sorted_students] # 绘制柱状图,直接用排序后的姓名作为x轴 plt.bar(sorted_names, sorted_scores, align='center', alpha=0.5, color=['b']) plt.ylabel('Score') plt.xlabel('Full Name') plt.title(f"{subject}'s Class Scores") # 姓名太长的话,旋转x轴标签避免重叠 plt.xticks(rotation=45, ha='right') plt.tight_layout() # 调整布局防止标签被截断 plt.show()
什么时候需要用类似y_pos的变量?
如果需要更灵活地控制柱子位置(比如做分组柱状图),可以用整数索引作为x轴位置,这时候y_pos就派上用场了:
y_pos = range(len(sorted_names)) plt.bar(y_pos, sorted_scores, align='center', alpha=0.5, color=['b']) plt.xticks(y_pos, sorted_names) # 这里用整数位置对应姓名标签,就不会错位了
内容的提问来源于stack exchange,提问作者Lyra Orwell
相关产品推荐
相关产品推荐

