Home > Enterprise >  Can Matplotlib return a bar's label using a mouse click event?
Can Matplotlib return a bar's label using a mouse click event?

Time:12-11

I'm trying to have a barchart return a bar's label when clicked, but I can't find an example where this particular task has been done on a bar chart. I found this sample barchart from Matplotlib, but it doesn't have any events set up:

import matplotlib.pyplot as plt
import numpy as np


labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # the label locations
width = 0.35  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, men_means, width, label='Men')
rects2 = ax.bar(x   width/2, women_means, width, label='Women')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x, labels)
ax.legend()

ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)

fig.tight_layout()

plt.show()

CodePudding user response:

First you need to add event handling to the Figure. You can do that with

fig.canvas.mpl_connect('button_press_event', onclick)

This tells matplotlib to run the function onclick whenever you click on your figure. onclick should have the signature

def onclick(event):

and you can access for example the x-coordinate of the mouse press using event.xdata. In your case, if you are always plotting the bars at each integer position on the x-axis, you can transform the x-coordinate of the press to the nearest integer and access that element of your labels. You can obtain the index for that element as

idx = int(event.xdata.round())

Finally, event.inaxes gets you the Axis-instance that you have clicked in, so you can access the axis labels with lbls = event.inaxes.get_xticklabels(). Then you can write onclick as

def onclick(event):
    ax = event.inaxes
    x = event.xdata
    lbls = ax.get_xticklabels()
    idx = int(x.round())
    lbl = lbls[idx]
    print(lbl.get_text())

to have the label of the nearest bar printed. This code will, however, still print something if you click between the bars. If you want to make sure that you are clicking a bar, you can get the rectangles used to plot the bar chart with ax.patches and check first whether the click was actually within one of the rectangles.

  • Related