How to use mplcursors with stacked bars in matplotlib
Question:
I am trying to create a stacked bar with matplotlib and getting stuck of using mplcursors.
When I run the program then it seems like all bars show the last data of the last person if I use (without [sel.index]):
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2]))
If I use:
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2][sel.index]))
Then I get the error list index out of range when I hover the bars.
Here is what I have so far. Any help will be greatly appreciated.
import matplotlib.pyplot as plt
import mplcursors
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)):
bar = plt.bar(y_pos[i], height=dict[nameList[i]][0], width=0.1, bottom=dict[nameList[i]][1])
info= mplcursors.cursor(bar, hover=True)
# info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2][sel.index]))
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2]))
plt.xticks(y_pos, nameList, rotation=90)
plt.show()
Answers:
There is in issue with the scope of the i variable inside the lambda function
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))
def create_bar_and_cursor(index, name, data):
bar = plt.bar(y_pos[index], height=data[0], width=0.1, bottom=data[1])
info = mplcursors.cursor(bar, hover=True)
info.connect("add", lambda sel: sel.annotation.set_text(data[2]))
return bar
for i, name in enumerate(nameList):
create_bar_and_cursor(i, name, data_dict[name])
plt.xticks(y_pos, nameList, rotation=90)
plt.show()
I am trying to create a stacked bar with matplotlib and getting stuck of using mplcursors.
When I run the program then it seems like all bars show the last data of the last person if I use (without [sel.index]):
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2]))
If I use:
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2][sel.index]))
Then I get the error list index out of range when I hover the bars.
Here is what I have so far. Any help will be greatly appreciated.
import matplotlib.pyplot as plt
import mplcursors
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)):
bar = plt.bar(y_pos[i], height=dict[nameList[i]][0], width=0.1, bottom=dict[nameList[i]][1])
info= mplcursors.cursor(bar, hover=True)
# info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2][sel.index]))
info.connect("add", lambda sel: sel.annotation.set_text(dict[nameList[i]][2]))
plt.xticks(y_pos, nameList, rotation=90)
plt.show()
There is in issue with the scope of the i variable inside the lambda function
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))
def create_bar_and_cursor(index, name, data):
bar = plt.bar(y_pos[index], height=data[0], width=0.1, bottom=data[1])
info = mplcursors.cursor(bar, hover=True)
info.connect("add", lambda sel: sel.annotation.set_text(data[2]))
return bar
for i, name in enumerate(nameList):
create_bar_and_cursor(i, name, data_dict[name])
plt.xticks(y_pos, nameList, rotation=90)
plt.show()