1

Suppose I have two numpy arrays x and y, and I would like to plot a simple curve of y as a function of x. At the y axis, I would like to put (as labels) the values of y, but at the x axis I would like to put as labels some function of the values there.

For example, if x=array([1, 2, 4, 8, 16]) and y=array([1, 2, 1, 2, 1]), I would like to assign labels to the xticks which will be the result of the following string formatting:

lambda x_val: "$2^{{+{:.0f}}}$".format(log2(x_val))

but I am interested in a general solution.

Bach
  • 6,145
  • 7
  • 36
  • 61

2 Answers2

6

Use matplotlib.ticker.FuncFormatter. Shamelessly copying and adapting the custom ticker example, something like this could work:

from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
from matplotlib import rc
import numpy as np

rc('text', usetex=True)

formatter = FuncFormatter(lambda x_val, tick_pos: "$2^{{+{:.0f}}}$".format(np.log2(x_val)))

x = np.array([1, 2, 4, 8, 16])
y = np.array([1, 2, 1, 2, 1])
fig, ax = plt.subplots()
ax.xaxis.set_major_formatter(formatter)
plt.plot(x, y)
plt.show()

which results in

enter image description here

Note that the first label is bad; there'll be a division by zero warning issued when you run the code. That is because matplotlib scales the axis between 0 and 16, and puts a tick mark at 0 (which is then passed to the formatter). You could turn off that tick mark, or scale the x-axis differently to avoid that.

  • I'm not sure - what should be wrong with the 1 in my `x` array? – Bach Jun 05 '14 at 09:24
  • 1
    @Bach you're correct, it's not the input data. It's the automatic scaling of the x-axis by matplotlib that causes it. I've updated my answer according to that. –  Jun 05 '14 at 10:00
0

For the case you have given:

import matplotlib.pylab as plt
import numpy as np

x = np.array([1, 2, 4, 8, 16]) 
y = np.array([1, 2, 1, 2, 1])

ax = plt.subplot()
ax.plot(x, y)

ax.set_xticks(x)
ax.set_xticklabels(["$2^{{+{:.0f}}}$".format(np.log2(x_val)) for x_val in x])

plt.show()

enter image description here

For a more general solution you will want to specify the x_values at which you want the ticks as x will in general have many more points than you want ticks. Either specify it manually or you can call ax.get_xticklabels() to get matplotlib to return the automated tick points.

For the most general method in which you simply tell matplotlib how you want the ticks formatted then see the Formatters section of Jake Vanderplas tutorial or the example in the docs.

Greg
  • 11,654
  • 3
  • 44
  • 50
  • 1
    Using `set_*ticklabels` is in general dangerous because it de-couples the labels from the data coordinates (the only reasonable use is putting text labels on a bar chart where the x-units are nonsense anyway). – tacaswell Jun 05 '14 at 13:41