Mastering Matplotlib: Formatting the Axes Like a Pro
Matplotlib is probably the most powerful plotting library for Python. However, it can be opinionated regarding how a plot should look like. If you want something different, everything is possible, but it can be surprisingly hard to achieve. In this article, we will focus on a common formatting issue: how to make a plot with xticks as multiples of π/2 and nicely formatted:
By default, Matplotlib will make a plot that shows raw integers along the x-axis and the frequency of the ticks along the y-axis is too high. This can make the plot look cluttered and unappealing:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(-2*np.pi, 2*np.pi, 200)
f = np.sin(x)
ax.plot(x, f);
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
To change the frequency of the ticks along the x-axiss, we set the major locator using
ax.xaxis.set_major_locator(MultipleLocator(0.5*np.pi))
. This function sets the major ticks to be spaced every half π units. The
MultipleLocator
function is a utility class that helps to define the spacing of the ticks on an axis. In this case, we set the spacing to be half π, which ensures that the ticks are evenly spaced and aligned with the data. For the y-axis, we just reduce the tick frequency to every 0.5:
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(-2*np.pi, 2*np.pi, 200)
f = np.sin(x)
ax.xaxis.set_major_locator(MultipleLocator(0.5*np.pi))
ax.yaxis.set_major_locator(MultipleLocator(0.5))
ax.set_xlabel('$x$')
ax.set_ylabel(r'$\sin(x)$')
ax.grid()
ax.plot(x, f);
Well, that is some progress. Along the x-axis, the ticks are really located at every multiple of π/2 but matplotlib is still using the numerical values. We want a nice formatting with π appearing as labels. To achieve that, we have to set the major formatter:
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(-2*np.pi, 2*np.pi, 200)
f = np.sin(x)
ax.xaxis.set_major_locator(MultipleLocator(0.5*np.pi))
ax.yaxis.set_major_locator(MultipleLocator(0.5))
def format_func(value, tick_number):
"""Formatter for setting the xticks to multiples of \pi/2."""
mult_pi_half = int(np.round(2 * value / np.pi))
sign = "-" if mult_pi_half < 0 else ""
if mult_pi_half == 0:
return "0"
elif abs(mult_pi_half) == 1:
return '$' + sign + r'\frac{\pi}{2}' + '$'
elif abs(mult_pi_half) == 2:
return '$' + sign + r'\pi $'
elif mult_pi_half % 2 > 0:
return r'$\frac{' + str(abs(mult_pi_half)) + '\pi}{2}$'
else:
return r"${0}\pi$".format(mult_pi_half // 2)
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
ax.set_xlabel('$x$')
ax.set_ylabel(r'$\sin(x)$')
ax.grid()
ax.plot(x, f);
Here, we defined a custom formatting function for the X-axis ticks using
plt.FuncFormatter(format_func)
. This function formats the labels for the X-axis ticks using integer multiples of π/2. The FuncFormatter function is a utility class that helps to format the labels of the ticks on an axis. It takes a formatting function as an argument, which is applied to the tick values to generate the formatted labels.
The
format_func
function takes two arguments:
value
, which is the value of the tick, and
tick_number
, which is the index of the tick. The latter is not used in our case, but is required by the matplotlib API. The function first calculates the multiple of π/2 that corresponds to the tick value. It then checks the sign of the multiple, and formats the label accordingly using a series of if-else statements.
Conclusion
In conclusion, we have shown how to nicely format the x-axis and y-axis in Matplotlib using the MultipleLocator and FuncFormatter functions. By setting the major locator for the x-axis, reducing the tick frequency for the y-axis, and formatting the tick labels using a custom function, we can create visually appealing and informative plots. With these techniques, you can customize the spacing, labels, and formatting of the ticks to create professional-looking plots in no time.