I have created a bar plot from a dataset, which has stacked bars of different values. What I want is that when I click on a box of a bar, to print the dataset that this box is coming from, not the whole dataset. For example in this code
import pandas as pd
import matplotlib.pyplot as plt
from itertools import product
codes = ['A', 'B', 'C', 'D']
months = ['January', 'February', 'March']
years = [2022, 2023]
rows = list(product(codes, months, years))
df = pd.DataFrame(rows, columns=['problem_code', 'month', 'year']).sample(n=20, random_state=42)
month_counts = df.groupby(['month','problem_code']).size().unstack(fill_value=0)
year_counts = df.groupby(['year','problem_code']).size().unstack(fill_value=0)
fig, (ax1, ax2) = plt.subplots(1, 2)
colors = ['blue', 'red', 'green', 'yellow']
# Plot the data for the months
bars1 = month_counts.plot(kind='bar', ax=ax1, stacked=True, color=colors)
# Plot the data for the years
bars2 = year_counts.plot(kind='bar', ax=ax2, stacked=True, color=colors)
plt.show()
print(month_counts)
when clicking on the box corresponding to January-problem code 'A' to show all the rows of the dataset with January as a month with problem code 'A', not the whole dataset. Same for year. Is this possible?
I tried using mplcursors but it doesn't seem to be able to distinct which one of the plots I am clicking on, so if for example I print the index of a box I can get index 1 from both plots.
With mplcursors, you can set a custom annotation function. That function get the selected object as parameter. In the case of a stacked bar plot, the selected object will be the container containing the clicked-on bar. The bars are grouped into containers depending on their color, depending on the column name in the dataframe. The column name will be used as label of the container.
The selection also has an
indexfield which can be used to find the bar. The bar is represented as a rectangle. Its height corresponds to the represented value. Theindexfield can further be used to get the x tick label of the bar.The subplot (
ax) can be retrieved via theaxesfield of the first bar in the container. If needed, a test such asif ax == ax1:can be used to find out which subplot has been clicked on.