Skip to content

FixedFormatter and FixedLocator Warning in Matplotlib ​

When working with matplotlib, you may encounter the warning: "UserWarning: FixedFormatter should only be used together with FixedLocator." This warning appears when trying to format axis labels without properly setting up the corresponding locator.

Problem Overview ​

The warning occurs when using set_xticklabels() or set_yticklabels() without ensuring the axis has a FixedLocator. Here's a typical problematic pattern:

python
def format_y_label_thousands():
    ax = plt.gca()
    label_format = '{:,.0f}'
    ax.set_yticklabels([label_format.format(x) for x in ax.get_yticks().tolist()])

This approach triggers the warning because matplotlib can't guarantee proper label placement when the locator isn't fixed.

Solution 1: Use tick_params() for Rotation ​

For simple formatting like label rotation, use tick_params() instead of manually setting tick labels:

python
# Instead of:
# ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
# Use:
ax.tick_params(axis='x', labelrotation=45)

Solution 2: Pair FixedFormatter with FixedLocator ​

When you need custom labels, explicitly pair FixedFormatter with FixedLocator:

python
from matplotlib import ticker

positions = [0, 1, 2, 3, 4, 5]
labels = ['A', 'B', 'C', 'D', 'E', 'F']
ax.xaxis.set_major_locator(ticker.FixedLocator(positions))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(labels))

Solution 3: Set Ticks Before Labels ​

Set the tick positions before setting their labels:

python
# For custom x-axis labels
ax.set_xticks([1, 2, 3])
ax.set_xticklabels(['Label1', 'Label2', 'Label3'])

Solution 4: Use FuncFormatter for Dynamic Formatting ​

For more complex formatting, use FuncFormatter:

python
from matplotlib import ticker

@ticker.FuncFormatter
def major_formatter(x, pos):
    return f'{x:.2f}'

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

Common Scenarios and Fixes ​

For Seaborn Heatmaps ​

python
heatmap = sb.heatmap(data, annot=True)
cbar = heatmap.collections[0].colorbar
cbar.ax.set_yticklabels(cbar.ax.get_yticklabels(), rotation=90)  # Warning
python
heatmap = sb.heatmap(data, annot=True)
cbar = heatmap.collections[0].colorbar
cbar.ax.tick_params(axis='y', labelrotation=90)  # No warning

For Date Ticks ​

python
import matplotlib.dates as dates
ax.xaxis.set_major_locator(dates.DayLocator())
ax.set_xticklabels(ax.get_xticklabels(), rotation=45)  # Warning
python
import matplotlib.dates as dates
ax.xaxis.set_major_locator(dates.DayLocator())
ax.tick_params(axis='x', labelrotation=45)  # No warning

Timing Matters ​

Ensure you format ticks after plotting your data. Setting tick labels before plotting can cause issues:

python
# Plot your data first
plt.boxplot(data)

# Then format ticks (after the plot call)
ax.set_xticklabels(['Label1', 'Label2'])  # Correct timing

WARNING

Avoid suppressing warnings globally with warnings.filterwarnings("ignore") as this may hide other important issues in your code.

Complete Working Example ​

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

# Create sample data
x = np.array(range(1000, 5000, 500))
y = 37 * x

fig, ax = plt.subplots()
ax.plot(x, y, linewidth=2, color='green')

# Format y-axis properly
ticks_loc = ax.get_yticks().tolist()
ax.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax.set_yticklabels([f'{x:,.0f}' for x in ticks_loc])

# Format x-axis with limited ticks
ax.xaxis.set_major_locator(mticker.MaxNLocator(3))
ticks_loc = ax.get_xticks().tolist()
ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax.set_xticklabels([f'{x:,.0f}' for x in ticks_loc])

plt.show()

Understanding the Warning ​

Matplotlib introduced this warning to prevent mismatches between tick positions and labels. When you use a FixedFormatter, matplotlib expects you to also use a FixedLocator to ensure each label corresponds exactly to a specific tick position.

By following the solutions above, you can format your matplotlib axes effectively while avoiding this common warning.