1

I would like to use ticklabel_format(style='plain') to suppress scientific notation on a logarithmic axis, but it is either ignored (first plot) or throws an exception (third plot, error shown below) depending on the order of the lines. It works however for a linear axis (second plot).

This happens both in versions 1.5.1 and 2.2.2 of Matplotlib.

Question: Why it it either ignored or fails for logarithmic axis and yet works fine for linear axis?


Traceback (most recent call last):
File "test.py", line 25, in <module>
ax3.ticklabel_format(style='plain', axis='x')
File "/Users/david/anaconda2/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 2805, in ticklabel_format
"This method only works with the ScalarFormatter.")
AttributeError: This method only works with the ScalarFormatter.

Here is the plot:

plot

import numpy as np
import matplotlib.pyplot as plt

x = np.logspace(-3, 3, 19)
y = np.log10(x)

fig = plt.figure()

ax1 = fig.add_subplot(3, 1, 1)
ax1.plot(x, y)
ax1.set_title("style='plain' is ignored", fontsize=16)
ax1.ticklabel_format(style='plain', axis='x')
ax1.set_xscale('log')

ax2 = fig.add_subplot(3, 1, 2)
ax2.plot(x, y)
ax2.set_title("style='plain' works", fontsize=16)
ax2.ticklabel_format(style='plain', axis='x')

if True:
    ax3 = fig.add_subplot(3, 1, 3)
    ax3.plot(x, y)
    ax3.set_title('THIS FAILS', fontsize=16)
    ax3.set_xscale('log')
    ax3.ticklabel_format(style='plain', axis='x')

plt.show()
uhoh
  • 3,713
  • 6
  • 42
  • 95
  • Have you tried using the ScalarFormatter try [here](https://stackoverflow.com/questions/21920233/matplotlib-log-scale-tick-label-number-formatting) – recurseuntilfor Apr 24 '19 at 09:47
  • @recurseuntilfor notice that it does work in the second case. It is only the compatability with log scale that is the problem. I will have a look now. – uhoh Apr 24 '19 at 09:54
  • @Sheldore I can get the plot to work, but my question is more than that. I've left a partial answer below, but the linked answer *does not explain* the the selective behavior of logarithmic versus linear scale. I've added the bold **Question:** section to make this clearer. I don't feel this is a duplicate, would you reconsider? – uhoh Apr 24 '19 at 10:06
  • @uhoh: Ok, retracted the vote – Sheldore Apr 24 '19 at 10:37
  • 2
    The answer to the question is simlpy that using a log scale sets the formatter to a `LogFormatter`. This `LogFormatter` does not have a `style='plain'` argument. The solution is, as shown in the duplicate, to use a `ScalarFormatter` instead. – ImportanceOfBeingErnest Apr 24 '19 at 10:57
  • Ok I made that linked answer more explicit on the fact that a log axis uses a different formatter. (The fact that `plain` is not supported by the formatter in use is clear enough from the error message,I would think.) – ImportanceOfBeingErnest Apr 24 '19 at 11:17
  • @ImportanceOfBeingErnest To me, logarithms *are* scalars, at least in mathematics. It's not obvious to someone who isn't knee-deep in matplotlib that scalar means "linear, not logarithmic". At least that's how it looks from my perspective and probably a lot of people who have used matplotlib for years without knowing that formatters even existed, much less what each name implies. – uhoh Apr 24 '19 at 11:20
  • @ImportanceOfBeingErnest anyway, thank you for the help. I'll go off and do my formatter homework now ;-) – uhoh Apr 24 '19 at 11:22
  • 1
    Yes, that is why you can use a ScalarFormatter without problem on a log axis, as everything is scalar. The name may be a bit confusing, it most probably comes from the fact that a number is a scalar, whereas on a log axis you use several values for formatting, i.e. the basis (like 10), the mantissa (mostly 1, but not always) and the exponent. This being said, even if it was named `FooBarFormatter`, would it change anything? Can the error message be made more clear? Where does a google search for `ScalarFormatter` lead, and is this documentation sufficient enough? If not, what can we change? – ImportanceOfBeingErnest Apr 24 '19 at 11:41
  • @ImportanceOfBeingErnest I was only addressing "...is clear enough from the error message, I would think." and explaining that it wouldn't be clear enough to someone who wasn't already familliar with the way formatters work. Yes everything is googlable, and SO is usually coming up first, *by design*, but it will still be necessary for me to do my "[formatter homework now](https://stackoverflow.com/questions/55826888/matplotlibs-ticklabel-formatstyle-plain-is-ignored-or-fails-for-logarithmic?noredirect=1#comment98322387_55826888)" before I start recognizing formatters, be they scalars or Foos. – uhoh Apr 24 '19 at 11:52

1 Answers1

2

I do not understand why the scientific notation is turned off for the linear axis and why it is either ignored or throws an exception only for the logarithmic axis, but based on this answer I can at least stop the bad behavior.

I still await an answer for why the three cases in the question produce different behavior.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

x = np.logspace(-3, 3, 19)
y = np.log10(x)

fig = plt.figure()

ax1 = fig.add_subplot(3, 1, 1)
ax1.plot(x, y)
ax1.set_title("style='plain' is ignored", fontsize=16)
ax1.ticklabel_format(style='plain', axis='x')
ax1.set_xscale('log')

ax2 = fig.add_subplot(3, 1, 2)
ax2.plot(x, y)
ax2.set_title("style='plain' works", fontsize=16)
ax2.ticklabel_format(style='plain', axis='x')

if True:
    ax3 = fig.add_subplot(3, 1, 3)
    ax3.plot(x, y)
    ax3.set_title('This now works!', fontsize=16)
    ax3.set_xscale('log')
    formatter = FuncFormatter(lambda y, _: '{:.16g}'.format(y)) # https://stackoverflow.com/a/49306588/3904031
    ax3.xaxis.set_major_formatter(formatter)

plt.show()

it works!

Sheldore
  • 37,862
  • 7
  • 57
  • 71
uhoh
  • 3,713
  • 6
  • 42
  • 95
  • 1
    `ax2.ticklabel_format(style='plain', axis='x')` seems to have no effect. You can just comment it out and re-run your code and you will see the middle plot is unchanged – Sheldore Apr 24 '19 at 10:40
  • @Sheldore ah, then plot 2 is a *moot demonstration*. Yes I see now, thanks. – uhoh Apr 24 '19 at 11:07