Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set x tick labels against the actual values of the series

I am trying to set x tick labels, but allowing matplotlib to decide where to place the ticks. Unfortunately, when I set the x tick labels, matplotlib will use the label strings only for the ticks that have been displayed.

Example:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
ax.plot(xs, ys)
ax.set_xticklabels(list('abcdefghijklmnopqrstuvwxyz'))
plt.show()

This gives:

enter image description here

This for me is quite unintuitive; I would expect the labels to correspond to the points that they are showing. (I can however understand this behavior is more useful when plotting multiple series which do not use the same x values.)

NB: I do not want all 26 letters as ticks. Rather, I want just the 6 (as matplotlib has suggested), but those 6 should be appropriate for their positions. This should then make it easy to change the fig size without having to manually recalculate the new tick labels.

How could I achieve the desired result?

like image 508
cammil Avatar asked Sep 14 '15 11:09

cammil


People also ask

How do you set the X-axis ticks?

xticks( ticks ) sets the x-axis tick values, which are the locations along the x-axis where the tick marks appear. Specify ticks as a vector of increasing values; for example, [0 2 4 6] . This command affects the current axes. xt = xticks returns the current x-axis tick values as a vector.

How do you add X ticks?

To add extra ticks, use xticks() method and increase the range of ticks to 1 to 20 from 1 to 10. To display the figure, use the show() method.

How do you change the X-axis labels in python?

MatPlotLib with Python Using subplot() method, add a subplot to the current figure. Plot x and log(x) using plot() method. Set the label on X-axis using set_label() method, with fontsize=16, loc=left, and color=red. To set the xlabel at the end of X-axis, use the coordinates, x and y.


2 Answers

You need to assign the tick location prior to the labels. The easiest way to get the desired result for your example would be to add ax.set_xticks(xs) before you set the tick labels.

import matplotlib.pyplot as pl
fig = pl.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
_ = ax.plot(xs, ys)
alph = list('abcdefghijklmnopqrstuvwxyz')
ax.set_xticks(xs)
ax.set_xticklabels(alph)
pl.savefig('ticklabels.png', dpi=300)

enter image description here

Edit: I'd suggest the following to address your wish for a more general solution:

from matplotlib.ticker import MaxNLocator
import matplotlib.pyplot as pl
import numpy as np

alph = list('abcdefghijklmnopqrstuvwxyz')
nticks = 8

fig, ax = pl.subplots()
xs = np.linspace(-10., 10., 100)
ys = np.polyval([1., 2., 3.], xs)

_ = ax.plot(xs, ys)

ax.xaxis.set_major_locator(MaxNLocator(nticks))
ax.set_xticklabels(alph[::int(len(alph)/nticks)])

pl.savefig('ticklabels.png', dpi=300)

You specify the number of ticks with the MaxNLocator and map them to the alphabet via slicing.

I'm not sure about how reliable MaxNLocator is in returning exactly the desired number of ticks, though. As mentioned in the comments, you could simply use len(ax.get_xticks()) to get the number of ticks.

enter image description here

like image 114
Daniel Lenz Avatar answered Oct 03 '22 09:10

Daniel Lenz


I think the most appropriate solution is to use FuncFormatter which will allow you to look up the tick label value you need, and allow matplotlib to determine positions and number of ticks:

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, MaxNLocator
fig = plt.figure()
ax = fig.add_subplot(111)
xs = range(26)
ys = range(26)
labels = list('abcdefghijklmnopqrstuvwxyz')


def format_fn(tick_val, tick_pos):
    if int(tick_val) in xs:
        return labels[int(tick_val)]
    else:
        return ''
ax.xaxis.set_major_formatter(FuncFormatter(format_fn))
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
ax.plot(xs, ys)
plt.show()

This will give you:

enter image description here

(Thanks Daniel Lenz for the pointers and other suggestions).

NB:

As mentioned by tcaswell, xaxis.set_major_locator(MaxNLocator(integer=True)) is used to ensure ticks are placed at integer values only.

like image 24
cammil Avatar answered Oct 03 '22 08:10

cammil