I've got a matplotlib graph with labelled X-ticks:
The labels repeat (in case that's relevant). In the real graph, there is a multi-level X-axis with more clarification in the lower layers.
That works fine, but I want to be able to hover the mouse and see the X-coordinate in the top-right of the graph. Whenever I set xticks to labels, I just get a blank X-coordinate:
If I use ax.xaxis.set_major_formatter('{x:g}')
, it gets rid of my labels but the cursor coordinate starts working:
Is there any way to make the cursor location still show the X coordinate even when I have a labelled X axis?
This also affects mplcursors
: it shows the X value as empty if I click on a line between points or with the label if I click exactly on a point (whereas I'd like to see the underlying numerical X-coordinate as "A" is a bit meaningless without the context from the secondary axis):
Source code:
import matplotlib.pyplot as plt
import numpy as np
import mplcursors
x = np.arange(0, 9)
y = np.random.rand(*x.shape)
labels = ['A', 'B', 'C']*3
fig, ax = plt.subplots()
ax.plot(x, y, 'bx-', label='random')
ax.set_xticks(x, labels=labels)
# This makes the coordinate display work, but gets rid of the labels:
# ax.xaxis.set_major_formatter('{x:g}')
mplcursors.cursor(multiple=True)
plt.show()
From [ Matplotlib mouse cursor coordinates not shown for empty tick labels ] adding ax.format_coord = lambda x, y: 'x={:g}, y={:g}'.format(x, y)
anywhere before plt.show()
makes it show the right coordinates.
If you want to display A
, B
or C
as x coordinates, you can make a custom coordinates format string function in which you round the current x position to an integer to get an index and get the corresponding label from labels
def custom_format_coord(x_val, y_val):
ix = int(round(x_val))
if 0 <= ix < len(labels):
x_label = labels[ix]
else:
x_label = f"{x_val}"
return f"x={x_label}, y={y_val:g}"
ax.format_coord = custom_format_coord