如何在Matplotlib堆叠条形图中正确使用mplcursors
问题解决:Matplotlib堆叠条形图与mplcursors的hover提示问题
问题根源分析
- 统一显示最后一组数据的原因
循环内的lambda函数会延迟绑定变量i,只有触发hover事件时才会读取i的当前值——循环结束后i已经指向最后一个索引(对应Tim),所以所有条形hover时都会显示Tim的数据。 - 索引越界错误的原因
加上sel.index后,触发事件时i同样指向最后一个索引(Tim),但Tim的提示文本列表仅含1个元素,而hover到其他用户的条形时,sel.index会是0、1、2这类大于0的数值,导致访问列表时超出范围。
修复后的完整代码
import matplotlib.pyplot as plt import mplcursors # 避免用dict作为变量名,防止覆盖Python内置类型 data_dict = {'Tom': ([10, 20, 40], [0, 15, 40], [1, 2, 3]), 'John': ([10, 20], [0, 12], [5, 6]), 'Tim': ([10], [0], [7])} nameList = ['Tom', 'John', 'Tim'] y_pos = range(len(nameList)) for i in range(len(nameList)): name = nameList[i] heights = data_dict[name][0] bottoms = data_dict[name][1] texts = data_dict[name][2] # 生成堆叠条形 bar_container = plt.bar(y_pos[i], height=heights, width=0.1, bottom=bottoms) # 用默认参数捕获当前迭代的texts,规避闭包延迟绑定问题 cursor = mplcursors.cursor(bar_container, hover=True) cursor.connect("add", lambda sel, texts=texts: sel.annotation.set_text(texts[sel.index])) plt.xticks(y_pos, nameList, rotation=90) plt.show()
关键修改说明
- 解决闭包延迟绑定:在lambda中添加
texts=texts作为默认参数,让每一次循环迭代都捕获当前用户的提示文本列表,而非事件触发时才读取变量值。 - 规范变量命名:将
dict改为data_dict,避免与Python内置类型冲突。 - 拆分变量提升可读性:把每个用户的高度、底部位置、提示文本拆分为单独变量,代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者VanN
相关产品推荐
相关产品推荐

