UserWarning: FixedFormatter should only be used together with FixedLocator

Each Answer to this Q is separated by one/two green lines.

I have used for a long time small subroutines to format axes of charts I’m plotting. A couple of examples:

def format_y_label_thousands(): # format y-axis tick labels formats
    ax = plt.gca()
    ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

def format_y_label_percent(): # format y-axis tick labels formats
    ax = plt.gca()
    ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

However, after an update to matplotlib yesterday, I get the following warning when calling any of these two functions:

UserWarning: FixedFormatter should only be used together with FixedLocator
  ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

What is the reason for such a warning? I couldn’t figure it out looking into matplotlib’s documentation.


The way to avoid the warning is to use FixedLocator (that is part of matplotlib.ticker). Below I show a code to plot three charts. I format their axes in different ways. Note that the “set_ticks” silence the warning, but it changes the actual ticks locations/labels (it took me some time to figure out that FixedLocator uses the same info but keeps the ticks locations intact). You can play with the x/y’s to see how each solution might affect the output.

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker

mpl.rcParams['font.size'] = 6.5

x = np.array(range(1000, 5000, 500))
y = 37*x

fig, [ax1, ax2, ax3] = plt.subplots(1,3)

ax1.plot(x,y, linewidth=5, color="green")
ax2.plot(x,y, linewidth=5, color="red")
ax3.plot(x,y, linewidth=5, color="blue")


# nothing done to ax1 as it is a "control chart."

# fixing yticks with "set_yticks"
ticks_loc = ax2.get_yticks().tolist()
ax2.set_yticklabels([label_format.format(x) for x in ticks_loc])

# fixing yticks with matplotlib.ticker "FixedLocator"
ticks_loc = ax3.get_yticks().tolist()
ax3.set_yticklabels([label_format.format(x) for x in ticks_loc])

# fixing xticks with FixedLocator but also using MaxNLocator to avoid cramped x-labels
ticks_loc = ax3.get_xticks().tolist()
ax3.set_xticklabels([label_format.format(x) for x in ticks_loc])



Sample charts

Obviously, having a couple of idle lines of code like the one above (I’m basically getting the yticks or xticks and setting them again) only adds noise to my program. I would prefer that the warning was removed. However, look into some of the “bug reports” (from links on the comments above/below; the issue is not actually a bug: it is an update that is generating some issues), and the contributors that manage matplotlib have their reasons to keep the warning.

If you use your Console to control critical outputs of your code (as I do), the warning messages might be problematic. Therefore, a way to delay having to deal with the issue is to downgrade matplotlib to version 3.2.2. I use Anaconda to manage my Python packages, and here is the command used to downgrade matplotlib:

conda install matplotlib=3.2.2

Not all listed versions might be available. For instance, couldn’t install matplotlib 3.3.0 although it is listed on matplotlib’s releases page:

If someone comes here using the function axes.xaxis.set_ticklabels() (or yaxis equivalent), you don’t need to use FixedLocator, you can avoid this warning using axes.xaxis.set_ticks(values_list) BEFORE axes.xaxis.set_ticklabels(labels_list).

According to this matplotlib page

# FixedFormatter should only be used together with FixedLocator. 
# Otherwise, one cannot be sure where the labels will end up.

This means one should do

positions = [0, 1, 2, 3, 4, 5]
labels = ['A', 'B', 'C', 'D', 'E', 'F']

But the issue also persisted with the ticker.LogLocator even if the labels were passed to ticker.FixedFormatter.
So the solution in this case was

  1. Define a formatter function

    # FuncFormatter can be used as a decorator
    def major_formatter(x, pos):
        return f'{x:.2f}'
  2. and pass the formatter function to the FixedFormatter

    ax.xaxis.set_major_locator(ticker.LogLocator(base=10, numticks=5))

See the above link for details.

Simplest workaround is to suppress warnings (this includes UserWarning):

import warnings

The use-case would be if you don’t want your jupyter notebook on github to look trashed with warning messages. Unlike most warnings, this warning keeps repeating if you’re in a loop (python 3.7).

I had the same problem as I tried to rotate the tick labels on the X-axis with located date ticks:

ax.set_xticklabels(ax.get_xticklabels(), rotation=45)

It worked out using the ‘tick_params()’ method:

ax.tick_params(axis="x", labelrotation = 45)

just use axis.set_xticks([labels])

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .