34

I'm experiencing a similar issue to the one reported here. I don't understand why the tick label text is an empty string:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi,100)
y = np.sin(x)**2

fig, ax = plt.subplots()
ax.plot(x,y)

labels = ax.get_xticklabels()
for label in labels:
    print(label)

plt.show()

Output:

Text(0,0,'')
Text(0,0,'')
Text(0,0,'')
Text(0,0,'')
Text(0,0,'')
Text(0,0,'')
Text(0,0,'')
Text(0,0,'')

I get the same result with ax.xaxis.get_ticklabels() but the plotted graph shows eight labelled ticks on the x-axis when saved or shown. However, if I ask for the labels after I show the plot, then the labels list is properly populated. Of course, it's a bit late to do anything about changing them then.

fig, ax = plt.subplots()
ax.plot(x,y)
plt.show()

labels = ax.get_xticklabels()
for label in labels:
    print(label)

Output:

Text(0,0,'0')
Text(1,0,'1')
Text(2,0,'2')
Text(3,0,'3')
Text(4,0,'4')
Text(5,0,'5')
Text(6,0,'6')
Text(7,0,'7')

Why does this happen (Mac OS X Yosemite, Matplotlib 1.5.1) and how can I get my labels before I show or save my plot?

Jacquot
  • 1,750
  • 15
  • 25
xnx
  • 24,509
  • 11
  • 70
  • 109
  • what is the purpose of getting `xticklabels`? You can always have your own custom `xticklabels` by using `ax.set_xticklabels(["0","1"])` (just an example). provide a list of strings as labels. If there are less no.of strings provided in the list, remaining `ticklabels` will show empty. reference: http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.set_xticklabels – Naveen Kumar R B Dec 13 '16 at 14:16

2 Answers2

41

You've correctly identified the problem: before you call plt.show() nothing is explicitly set. This is because matplotlib avoids static positioning of the ticks unless it has to, because you're likely to want to interact with it: if you can ax.set_xlim() for example.

In your case, you can draw the figure canvas with fig.canvas.draw() to trigger tick positioning, so you can retrieve their value.

Alternatively, you can explicity set the xticks that will in turn set the the axis to FixedFormatter and FixedLocator and achieve the same result.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi,100)
y = np.sin(x)**2

fig, ax = plt.subplots()

ax.plot(x,y)
ax.set_xlim(0,6)

# Must draw the canvas to position the ticks
fig.canvas.draw()
# Or Alternatively
#ax.set_xticklabels(ax.get_xticks())

labels = ax.get_xticklabels()
for label in labels:
    print(label.get_text())

plt.show()

Out:
0
1
2
3
4
5
6
Julien Marrec
  • 11,605
  • 4
  • 46
  • 63
  • 5
    This solution does not work when the `pdf`-backend is used. In this case, `ax.get_xticklabels()` is unaffected by `fig.canvas.draw()`. While the alternate solution `ax.set_xticklabels(ax.get_xticks())` has ticklabels produced, indeed, they differ from the ones that would otherwise be produced: `ax.set_xticklabels(ax.get_xticks())` produces 0.0, 1.0, 2.0 ... `fig.canvas.draw()` produces 0, 1, 2, ... – Bastian Feb 25 '19 at 11:45
  • So I'm not using subplots() and I also have empty `ax.get_yticklabels()` when looping. And a `fig.canvas.draw()` give me an error. – tvdsluijs Sep 04 '22 at 09:59
0

As Julien Marrec, you have to call fig.canvas.draw(). Good thing is it doesn't wait for input after opening window and directly displays the chart(or returns control to next line in code)

So I made a workaround here:

# First call the .draw() function and take whatever values your need.
fig.canvas.draw()
x_lab = axes.get_xticklabels()
y_lab = axes.get_yticklabels()
z_lab = axes.get_zticklabels()

# Now we close the figure since we are done getting values
# This will be a fast process and look like figure never opened
plt.close()
Mark
  • 1