<ipython-input-3-52a3699e4278>:5: UserWarning: FixedFormatter should only be used together with FixedLocator
ax.set_xticklabels(['0', r'$T/2$', r'$T$'])
Expected outcome
Works on 3.2.2 with no warning.
Matplotlib version
Operating system: Win 10
Matplotlib version: 3.3.2
Matplotlib backend: module://ipykernel.pylab.backend_inline
Python version: 3.8.5
Jupyter version (if applicable): 6.1.4
Other libraries: none
Installed from conda
That's on purpose. You should also explicitly specify the three ticks to go with the label and then this warning should go away.
OTOH I agree the warning is pretty mysterious if u are just using set_xticklabels.
I see. It would be good to fix the message.
Also, If you do set the tick locations, you have to do it first (I revised my code sample to show this). Yes, it's cleaner to set the locations first and then the labels, but I don't think it should be a warning. As long as the locator and labels have both been set by the time the plot is drawn, it should be OK.
Thanks, @jklymak: now I understand why the warning was included. However, I'm assuming there is a lot of code out there - the one I use the most on a day-to-day basis included - that only plots "fixed" charts. Therefore, having to add a line of code using FixedLocator (if what I want is just to format the existing labels), would make the conde unnecessarily polluted, no? Maybe the potential issue you describe should be included somewhere on matplotlib's documentation?
Its a warning that you are doing something poorly defined. If you want to suppress it either specify the ticks
ax.set_xticks([1, 2, 3])
ax.set_xticklabels(['$\pi$', '$2\pi$', '$3\pi$'])
filter the Warning, or just ignore it.
VongCanhChi, FanchenBao, mahdiaslanimk, wenyuan-wu, wilswer, Shelly-Lee, BitnaKeum, L-Marriott, M4thinking, Sheshadri-1992, and mandresyandri reacted with thumbs up emoji
IcyW and jorgeUnas reacted with laugh emoji
All reactions
Side note: I'm tempted to modify set_ticks()
from set_ticks(ticks, *, minor=False)
to set_ticks(ticks, *, labels=None, minor=False)
.
That would allow to set_ticks([1, 2, 3], labels=['$\pi$', '$2\pi$', '$3\pi$'])
and would exactly prevent this problem. A bit hesitant because that'd break the symmetry between get/set. OTOH it does not make sense to set labels without controlling positions, and that's most of the time best done by setting both simultaneously.
Note also that pyplot.xticks()
does something siimilar, though it fully merges set_ticks
and set_ticklabels`; and I don't think we can mimic this on the Axes due to backward-compatibility (whether that'd be a good idea would need to be evaluated separately..
This worked fine in a similar situation:
ax.set_xticks(ax.get_xticks()) # just get and reset whatever you already have
ax.set_xticklabels(xtick_labels) # set the new/modified labels
A single parameter would work relatively well also if you start with two lists, either as dict
set_xticks(dict(zip(positions, labels)))
and/or as list of tuples
set_xticks(zip(positions, labels))
My concern is however, that we basically don't have such compound parameters in our API and mostly use separate parameters.
Hm can someone summarize the suggested solution after #20047?
Basically I want to do string formatting of the form ax.set_xticklabels([f(t) for t in ax.get_xticklabels()])
. I tried using a FuncFormatter
, but couldn't get it to work, presumably because I'm using pandas which does something under the hood.
Example:
import pandas as pd
from matplotlib.ticker import FuncFormatter
pd.Series({'a': 10, 'b': 20, 'c': 30}).plot.bar()
ax = plt.gca()
formatter = FuncFormatter(lambda x, pos: f"{x}, {pos}")
ax.xaxis.set_major_formatter(formatter)
I would have expected x
to be a
, b
and c
but it's not.
What I had before was something like
pd.Series({'a': 10, 'b': 20, 'c': 30}).plot.bar()
ax = plt.gca()
ax.set_xticklabels([f"{x.get_text()}_is_great" for x in ax.get_xticklabels()])
Those are categorical plots; the axis is not the categories, but 0, 1, 2, 3... which is transformed by StrCategoryFormatter
into the correct labels. You will probably want to grab the existing formatter, wrap its result, and return that back. Something like:
import matplotlib.ticker as mticker
class SpecialFormatter(mticker.Formatter):
def __init__(self, original_formatter):
self.original_formatter = original_formatter
def __call__(self, x, pos=None):
x = self.original_formatter(x, pos=pos)
return f"{x}, {pos}"
ax.xaxis.set_major_formatter(SpecialFormatter(ax.xaxis.get_major_formatter()))
Thanks, I figured that the category-indexes were transformed by a formatter.
I feel that requires a lot more knowledge of the internals than what I was doing before, and it's quite a common operation.
Basically if you want to apply a function to the ticks in an existing plot, this is what you have to do. Was that the suggested solution before as well?
Basically this is a DerivedFuncFormatter
that allows me to apply a function to the existing formatter, so it's a bit more complicated than what @jklymak suggested above. For a library this works as a recipe, for a notebook it's not very convenient.
Sorry if I'm not following, what is wrong with the following? It seems to work fine with categoricals?
ax.set_xticklabels([f"{x.get_text()}_is_great" for x in ax.get_xticklabels()])
I ran into the same issue as @amueller - attempting to use FuncFormatter
on tick labels that were internally stored as categories. You have to have deep knowledge of Matplotlib to understand what is going on as the labels appear as strings in the plot but are stored as numeric internally.
The easiest solution seems to be:
ax.set_xticklabels([my_func(x.get_text()) for x in ax.get_xticklabels()])
* removed automatically reading the problem in each Optimize-/Profile-/Sample-reader. Set default argument for reading problem to false as the problem can in general not be stored completely.
* fix matplotlib warning. More on this here: matplotlib/matplotlib#18848
* fixed warning for missing burn in by performing geweke test within test pipeline.
* fixed warning for usage of distplot, as this will be removed in a future seaborn version.
* added probability as stat to normalize.
* added comment regarding axis argument error in seaborn. Not sure how to fix.
* changed `bw` to `bw_method`.
* changed `bw` to `bw_method`. Fixed a typehint.
* reworked FixedLocator warning.
* remove DeprecationWarning: Flags not at the start of the expression '^(?i)(ls_)'.
* fixed problem with MPI pool engine test.
* fixed problem in set_yticks. Missing parentheses.
* fixed ValueError in set_yticklabels.
* increased possible runtime on tests.
* fixed notebook `hdf5_storage.ipynb`.
* put timeout minutes back to 10min again
Co-authored-by: Yannik Schälte <[email protected]>
Directly setting axis labels raises a warning from matplotlib that
results may not be correct in every display scenario. We don't currently
hit those cases here, but this resolves the warnings in a more general
See: matplotlib/matplotlib#18848
Co-authored-by: Ben Williams <[email protected]>
matplotlib 3.3 and above gives a warning when calling `get_shift_graph`:
UserWarning: FixedFormatter should only be used together with FixedLocator
This issue explains why the warning occurs and suggests setting xticks first before setting xticklabels: matplotlib/matplotlib#18848
matplotlib 3.3 and above gives a warning when calling `get_shift_graph`:
UserWarning: FixedFormatter should only be used together with FixedLocator
This issue explains why the warning occurs and suggests setting `xticks`
first before setting `xticklabels`:
matplotlib/matplotlib#18848