1. Introduction

Ticks on axes help us orient in a plot and understand the mapping from the x to y values. Usually, major ticks are labeled, while minor ticks are drawn without labels to avoid cluttering the plot.

In this tutorial, we’ll explain four ways to customize ticks in Matplotlib:

  • use set_xticks() and set_yticks() to manually set the locations and labels of the major and minor ticks
  • use Locator and Formatter classes to automatically determine, position, and label axis ticks
  • customize the appearance of tick lines and labels via tick_params()
  • *use loglog(), semilogx(), and semilogy() to quickly set logarithmic scales* on one or both axes

We’ll illustrate these methods on numeric data. The Matplotlib documentation explains how to set ticks for time series and dates.

2. Why Customize Ticks?

Matplotlib has a pretty good default system of choosing tick values and formatting their labels, but sometimes, we need to customize the ticks.

For example, if we plot trigonometric functions, it makes sense to use the multiples of pi as ticks on the x-axis. However, Matplotlib doesn’t interpret plots, so it doesn’t know that the multiples of pi are natural ticks in this case.

3. Set Tick Locations and Labels Manually

To set major and minor ticks on the x-axis, we can use the set_xticks() method of the Axes object in the object-oriented API or matplotlib.pyplot.xticks() in the state-based API of Matplotlib.

Here’s the syntax of set_xticks():

axs.set_xticks(ticks, labels=None, *, minor=False, **kwargs)

Here:

  • axs is the Axes object for which we’re setting the ticks of the x-axis
  • ticks is the list or an array of the tick values
  • labels is the array of labels and has to be of the same size as ticks
  • minor=False means we’ll set the major ticks, and minor=True indicates we’ll set the minor ticks
  • kwargs are keyword arguments we can pass to format the labels if the array labels is set

If labels=None, Matplotlib will use its default system to determine the labels:

  • Major ticks’ values will be used as labels
  • Minor ticks will have no labels

*This also holds for the y-axis, for which we have set_yticks() and matplotlib.pyplot.yticks().*

3.1. Example

As we said, it’s more meaningful to have the multiples of pi as ticks for a trigonometric function. Let’s set the major ticks to integer multiples and minor ticks to the multiples of 0.5pi in the plot of the sine function:

import matplotlib.pyplot as plt
import numpy as np

# The x and y values for the sine function
x = np.linspace(0, 6, 500) * np.pi
y = np.sin(x)

# Create a figure
fig, axs = plt.subplots(figsize=(5, 4))

# Plot the sine line 
axs.plot(x, y)

# Set the major ticks to the multiples of pi: 0, pi, 2pi, 3pi, 4pi, 5pi, 6pi
major_ticks = np.arange(0, 6.1, 1) * np.pi
# Use 0, pi, 2pi, ..., 6pi as tick labels
major_labels = ['0', ''] + [f'' for i in [2, 3, 4, 5, 6]]

# Set the minor ticks to 0, pi/4, pi/2, ...
minor_ticks = np.arange(0, 6.1, 0.5) * np.pi
# Use empty labels
minor_labels = np.repeat('', len(minor_ticks))

# Set the major and minor ticks on the x axis
axs.set_xticks(major_ticks, labels=major_labels, minor=False)
axs.set_xticks(minor_ticks, labels=minor_labels, minor=True)

We use LaTeX formatting to get the math \pi symbol*.* The result is:

Set ticks manually in Matplotlib

These ticks are much more meaningful than the default ones:

Default ticks for the sine function

In this example, we set the labels and minor parameters explicitly, but if we used their default settings, we could get the same results:

axs.set_xticks(major_ticks, labels=major_labels)
axs.set_xticks(minor_ticks, minor=True)

4. Using Locators and Formatters

In Matplotlib, we have two classes that specify the position of ticks and the appearance of their labels: Locator and Formatter.

We subclass them to implement our own locators and formatters or use the pre-existing classes that come with Matplotlib and cover many use cases.

Their advantage over the manual approach is that they automatize the calculation and label formatting. For instance, if we changed the x range for the sine function, we’d have to adjust the x ticks explicitly. However, with a locator, we’d implement a rule for choosing the ticks, which would be applied to any range of the x values.

4.1. Locators

A locator is an object of the Locator class or its subclass. It specifies the positions of axis ticks based on the range of values the axis covers.

Matplotlib has several ready-to-use locators, and here are some of them:

Locator

Description

MaxNLocator

Selects and uses no more than the given number of points as ticks.

AutoLocator

The default locator. Essentially, MaxNLocator with the default parameter settings.

LinearLocator

Ticks are evenly spaced between the axis endpoints.

LogLocator

The logarithms of the ticks are evenly spaced between the axis endpoints.

MultipleLocator

Tick values are multiples of the same base value plus an optional offset.

FixedLocator

Ticks are fixed values.

NullLocator

The axis is without ticks.

These locators are in matplotlib.ticker and can override the major and minor locators on both axes:

axs.xaxis.set_major_locator(x_major_locator)
axs.xaxis.set_minor_locator(x_minor_locator)
axs.yaxis.set_major_locator(y_major_locator)
axs.yaxis.set_minor_locator(y_minor_locator)

We reference the x-axis of the Axes object axs as axs.xaxis. Similarly, we access the y-axis as axs.yaxis. *To set the locators for the minor and major ticks, we use the methods set_major_locator() and set_minor_locator().*

4.2. Example With Locators

Let’s set the major ticks:

import matplotlib.pyplot as plt
from matplotlib.ticker import AutoLocator, MaxNLocator, LinearLocator, LogLocator, MultipleLocator
import numpy as np

# Generate data
x = np.linspace(0, 5, 100) * np.pi
y = np.sin(x)

# Make a figure with five subplots
fig, axs = plt.subplots(nrows=5,
                        ncols=1, 
                        figsize=(5, 5),
                        layout='constrained')
axs[0].plot(x, y)
axs[0].xaxis.set_major_locator(AutoLocator())
axs[0].set_title('AutoLocator')

axs[1].plot(x, y)
axs[1].xaxis.set_major_locator(MaxNLocator(nbins=4))
axs[1].set_title('MaxNLocator(nbins=4)')

axs[2].plot(x, y)
axs[2].xaxis.set_major_locator(LinearLocator(numticks=5))
axs[2].set_title('LinearLocator(numticks=5)')

axs[3].plot(x, y)
axs[3].xaxis.set_major_locator(LogLocator(numticks=5))
axs[3].set_title('LogLocator(numticks=5)')

axs[4].plot(x, y)
axs[4].xaxis.set_major_locator(MultipleLocator(base=np.pi))
axs[4].set_title('MultipleLocator(base=3.14)')

fig.savefig('matplotlib_locators.jpg', dpi=300, bbox_inches='tight')

We created a figure with five subplots. In MultipleLocator, we used pi as the base. We instructed LinearLocator to use five ticks, MaxNLocator to use at most four, and LogLocator to use no more than five:

Tick locators

By default, LogLocator uses 10 as the base and integers as exponents. Only the powers 10^0=1 and 10^1=10 were shown as ticks because the data range is [0, 5pi).

4.3. Formatters

A formatter is an object of the Formatter class or its subclass. While a locator chooses tick values, a formatter specifies how they will be displayed in the corresponding tick labels.

Here are some of the Matplotlib ready-to-use formatters:

Formatter

Decription

FixedFormatter

Fixed strings are used as labels.

StrMethodFormatter

Uses a format string to turn a tick value into a label.

FuncFormatter

A user-defined function formats values as labels.

ScalarFormatter

Formats the tick values as numbers.

PercentFormater

A tick’s label is the ratio of the tick’s value to the parameter xmax and is expressed as a percentage.

NullFormatter

No labels are used.

*We set the formatters using the methods set_major_formatter() and set_minor_formatter():*

axs.xaxis.set_major_formatter(x_major_formatter)
axs.xaxis.set_minor_formatter(x_minor_formatter)
axs.yaxis.set_major_formatter(y_major_formatter)
axs.yaxis.set_minor_formatter(y_minor_formatter)

Note that a user function is automatically converted into FuncFormatter and a format string into StrMethodFormatter. A format string should denote the tick value as x.

4.4. Example with Formatters

Now, let’s try out various formatters while using the multiples of pi as tick values.

We’ll use the following function for FuncFormatter:

def format_func(x, pos):
    r = x / np.pi
    if r == 0:
        return '0'
    elif r == 1:
        return ''
    else:
        if np.isclose(r, round(r)):
            return f''
        else:
            return f''

It will produce labels 0, pi, 2pi, 3pi… or 2.15pi, 3.45pi, etc., if the value isn’t an integer multiple of pi.

Matplotlib will instantiate FuncFormatter if we supply a function to the formatter setter. Similarly, a string will be converted to StrMethodFormatter:

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, ScalarFormatter, PercentFormatter, MultipleLocator
from matplotlib.ticker import FixedLocator, FixedFormatter
import numpy as np

# Generate data
x = np.linspace(0, 5, 100) * np.pi
y = np.sin(x)

# Make a figure with a subplot grid
fig, axs = plt.subplots(nrows=5,
                        ncols=1, 
                        figsize=(5, 4),
                        layout='constrained')

# Set the locator and plot the line
for ax in axs:
    ax.xaxis.set_major_locator(MultipleLocator(base=np.pi))
    ax.plot(x, y)

# Set the formatters for the subplots

axs[0].xaxis.set_major_formatter(ScalarFormatter())
axs[0].set_title('ScalarFormatter')

axs[1].xaxis.set_major_formatter('{x:.3f}')
axs[1].set_title('StrMethodFormatter')
            
axs[2].xaxis.set_major_formatter(format_func)
axs[2].set_title('FuncFormatter')

max_x = np.round(max(x), 2)
axs[3].xaxis.set_major_formatter(PercentFormatter(xmax=max_x))
axs[3].set_title(f'PercentFormatter(xmax={max_x})')

# For FixedFormatter, use FixedLocator; otherwise, the label placement is unpredictable
axs[4].xaxis.set_major_locator(FixedLocator(np.arange(0, 6.1, 1) * np.pi))
axs[4].xaxis.set_major_formatter(FixedFormatter(['A', 'B', 'B', 'D', 'E', 'F']))
axs[4].set_title('FixedLocator + FixedFormatter')

The result:

matplotlib formatters

FixedFormatter should be used with FixedLocator to place the labels next to the tick marks. If we use another locator, the placement of the tick labels will be unpredictable.

5. Change the Appearance Using tick_params()

The tick_params() method of Axes objects sets the visual elements of ticks and their labels in the plot, such as color and size. We need to specify the axis (‘x’, ‘y’, or ‘both’) and tick type (‘major’, ‘minor’, or ‘both’) for which the settings will apply.

For example:

fig, axs = plt.subplots(figsize=(5, 4))

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

axs.plot(x, y)
axs.xaxis.set_major_locator(MultipleLocator(np.pi))

axs.tick_params(
    axis='x',            # which axis
    which='major',       # which ticks
    direction='inout',   # are ticks inside or outside the plot, or cross the axis
    length=20,           # tick length
    width=4,             # tick width
    color='#9e4244',     # tick color
    pad=5,               # distance between ticks and labels
    labelsize=13,        # label font
    labelrotation=15,    # label angle
    labelcolor='#fc4c4e' # label color
)

Here’s how the plot looks:

Change the appearance of ticks and their labels using tick_params()

6. Shortcuts for Logarithmic Scales

Logarithmic scales are used so often that Matplotlib provides specialized plotting methods that set the axes to use logarithms and handle tick locations and label formatting for us. Those are:

  • loglog(): both axes use the logarithmic scale with the same base
  • semilogx(): the x-axis will be logarithmic
  • semilogy(): the y-axis will be logarithmic

All three methods take the following parameters:

  • base: the base of the logarithm (default value = 10)
  • subs: the minor ticks’ locations
  • nonpositive: if set to ‘mask’, it masks nonpositive values as invalid, and if set to ‘clip’, replaces them with a small positive number.

We use these methods the same way as plot():

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0.1, 1000, 500)
y = x**1.5 - x

fig, axs = plt.subplots(nrows=2, ncols=2,
                        layout='constrained',
                        figsize=(6.5, 6.5))

axs[0][0].plot(x, y)
axs[0][0].set_title('(x, y)')

axs[0][1].semilogx(x, y)
axs[0][1].set_title('(log_10 x, y)')

axs[1][0].semilogy(x, y)
axs[1][0].set_title('(x, log_10 y)')

axs[1][1].loglog(x, y)
axs[1][1].set_title('(log_10 x, log_10 y)')

Here’s the resulting figure:

Logarithmic scales

Here, we changed the axis scales, not just the ticks, so the shape of the line changed as well.

7. Conclusion

In this article, we presented four ways to control ticks and their labels in Matplotlib plots. The manual method with set_xticks() and set_yticks() is suitable for one or two plots, but if we need to specify the tick settings for multiple plots, it’s better to use locators and formatters.

To learn more about Matplotlib:


原始标题:Changing the Ticks on the x or y Axis in Matplotlib