Reputation: 2682
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()
label_format = '{:,.0f}'
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()
label_format = '{:.1%}'
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.
Upvotes: 119
Views: 154125
Reputation: 1045
labels = ['your', 'labels', 'here']
ax.set_xticks(ax.get_xticks(), labels=labels)
Upvotes: 0
Reputation: 761
I know it's a silly answer, but maybe someone had the same problem... I was setting labels before plotting data (in a box plot) and got the warning, added set_xtikcs(range(len(data)) and warning disappeared but labels too, moving set_xticklabels after plot fixed everything, even without set_xticks call.
Upvotes: 0
Reputation: 2582
ax.set_xticks(ax.get_xticks())
ax.set_yticks(ax.get_yticks())
^ this removes the warning for every data/plot case I've encountered.
I keep bumping into this warning and to @dansarmo's answer. It is basically their answer. Thanks for correction by @als0052 and @Hampus Larsson's comment for noting the bug report and solution with set_*ticks
.
Upvotes: 3
Reputation: 196
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
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))
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
Define a formatter function
# FuncFormatter can be used as a decorator
@ticker.FuncFormatter
def major_formatter(x, pos):
return f'{x:.2f}'
and pass the formatter function to the FixedFormatter
ax.xaxis.set_major_locator(ticker.LogLocator(base=10, numticks=5))
ax.xaxis.set_major_formatter(major_formatter)
See the above link for details.
Upvotes: 11
Reputation: 565
My case was a simple thing, I was customizing ticks before creating the plot itself, which resulted in trying to format something that had not been set to my expected number of ticks yet.
Make sure that if for example you are making a boxplot, edit the ticks AFTER the plt.boxplot()
call.
Upvotes: 0
Reputation: 1357
I also have the UserWarning: FixedFormatter should only be used together with FixedLocator warning when doing:
ax2.xaxis.set_major_locator(mdates.DayLocator(bymonthday=ttick_solar))
ax2.set_xticklabels(label_solar)
I tried to encapsulate mdates.DayLocator(bymonthday=ttick_solar) in a mticker.FixedLocator but i must do it wrongly. What would be the correct syntax to do it?
Thanks
Upvotes: 0
Reputation: 27224
In my case I was using a seaborn
heatmap
and this is how I fixed it:
This was throwing the warning UserWarning: FixedFormatter should only be used together with FixedLocator cbar.ax.set_yticklabels(cbar.ax.get_yticklabels(), rotation=90, va='center')
heatmap = sb.heatmap(pd.DataFrame(full_dict).T.fillna(0), annot=True, linewidths=1, xticklabels=1, yticklabels=1, annot_kws={'rotation': 90})
cbar = heatmap.collections[0].colorbar
cbar.ax.set_yticklabels(cbar.ax.get_yticklabels(), rotation=90, va='center')
I changed it to the following in order to suppress the warning:
heatmap = sb.heatmap(pd.DataFrame(full_dict).T.fillna(0), annot=True, linewidths=1, xticklabels=1, yticklabels=1, annot_kws={'rotation': 90})
cbar = heatmap.collections[0].colorbar
cbar.ax.tick_params(axis='y', labelrotation=90)
Thanks to @Rami's answer: https://stackoverflow.com/a/72099702/264802
Upvotes: 1
Reputation: 71
I solved just adding this sentence:
ax.set_xticks([1,2,3])
ax.set_xtickslabels(['Label1', 'Label2', 'Label3'])
Upvotes: 7
Reputation: 708
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)
ax.xaxis.set_major_locator(dates.DayLocator())
It worked out using the 'tick_params()' method:
ax.tick_params(axis='x', labelrotation = 45)
Upvotes: 32
Reputation: 6665
Simplest workaround is to suppress warnings (this includes UserWarning):
import warnings
warnings.filterwarnings("ignore")
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).
Upvotes: 2
Reputation: 1037
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)
.
Upvotes: 102
Reputation: 2682
WORKAROUND:
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')
label_format = '{:,.0f}'
# nothing done to ax1 as it is a "control chart."
# fixing yticks with "set_yticks"
ticks_loc = ax2.get_yticks().tolist()
ax2.set_yticks(ax1.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.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
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
ax3.xaxis.set_major_locator(mticker.MaxNLocator(3))
ticks_loc = ax3.get_xticks().tolist()
ax3.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax3.set_xticklabels([label_format.format(x) for x in ticks_loc])
fig.tight_layout()
plt.show()
OUTPUT 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.
OLDER VERSION OF MATPLOTLIB: 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: https://github.com/matplotlib/matplotlib/releases
Upvotes: 79