0

I would like to plot the following data and I cannot seem to get matplotlib to show more axis labels.

import matplotlib.pyplot as plt
from matplotlib.ticker import LogLocator, LogFormatterMathtext
fig, ax = plt.subplots()
ax.set_yscale("log")
ax.get_yaxis().set_major_locator(LogLocator(subs=(1,2,3,4,5,6,7,8,9,)))
ax.get_yaxis().set_major_formatter(LogFormatterMathtext(base=10))
ax.plot([1,2,3,4,5], [4500, 4000, 1000, 500, 450])
plt.show()

The result:

Only one label is shown

The expected result would have labels such as 2 × 10³, 3 × 10³ etc. without an offset.

chrslg
  • 9,023
  • 5
  • 17
  • 31
spurdo
  • 3
  • 1
  • 3
    What offset? And which label is not in scientific notation here? – chrslg Nov 10 '22 at 20:53
  • I don't want it to say 1, 2, 3 on the left and 10³ at the top. And I don't mean that labels are in a notation that's not scientific, the major ticks just don't have labels at all. – spurdo Nov 11 '22 at 09:54
  • I really don't understand. It is as if you were commenting a different image than the one we have before our eye! You have no offset nowhere in this picture. You have a x-axis for which there is no difference between scientific notation and other (1, 1.5, 2, ... 5 are scientific notation. Saying 1×10⁰, 1.5×10⁰, ... is not "scientific"). And you have a y-axis, with no offset, in logarithmic scale, with all labelled ticks (that is only one) labelled in scientific notation (namely 10³, the only power of 10 there is in y range) – chrslg Nov 11 '22 at 11:13
  • So, is your problem just that you want more ticks to be labelled on y-axis? If so, why mention "scientific notation" when everything is already in scientific notation, and why mention offset, when there isn't one on the picture? – chrslg Nov 11 '22 at 11:14
  • Yes, that's the main issue: I want more ticks to be labelled. I mentioned it because without the "scientific notation" (2×10³ etc.) it works. Only when I format the labels like this, I can't seem to produce the additional labels. >(namely 10³, the only power of 10 there is in y range) I was trying to produce labels at integer multiples of every power of 10 as well. That was the idea behind line 5 of my code snippet. – spurdo Nov 11 '22 at 12:10
  • Ok, so, this has nothing to do with offset, since there is no offset here, and you don't want one. As for Scientific notation, you've not chosen the correct Formatter then. Mathtext would display everything in the form "10ˢᵒᵐᵉᵗʰⁱⁿᵍ" not "x.10ᵏ". For example "10³˙³⁰" instead of "2×10³". – chrslg Nov 11 '22 at 13:03

1 Answers1

1

So first thing, you don't obviously want LogFormatterMathtext. That would produce this kind of images if you had your way with "one label per tick" (we'll come to that in one moment).

enter image description here

The one you want is LogFormatterSciNotation. (LogFormatter alone would label "500", "600", "700", "800", "900", "1000", "2000", "3000", etc. ; LogFormatterExponent: 2.7, 2.78, 2.85, 2.9, 2.95, 3, 3.3, 3.48, ... ; the one you've chosen, same thing, but with 10ˣ : 10²·⁷, 10²·⁷⁸, 10²·⁸⁵, ... ; LogFormatterSciNotation is the one that would label 5×10², 6×10², 7×10²,8×10²,9×10², 10³, 2×10³, ...)

Secondly, you have to distinguish creating ticks (you did that with LogLocator), and deciding where are the labels. Ticks are not all labelled. Even major ticks. That depends on the formatter. Most formatters has default settings that makes them display more label for major ticks than for minor ticks. Yet, it is not "all" and "nothing". Especially for LogFormatter*

So, one parameter of LogFormatter* is labelOnlyBase. You want this to False. Otherwise, only power of 10 are labelled. So only "10³" in your case.

And that is not enough. Because even if the LogFormatter has nothing against labelling non 10 power, it also has some criteria about how many ticks has to be labelled, to avoid to much label density. So, that does not depends only on formatter, but also on the range of your y-axis. This is minor_thresholds parameter. To which you give a pair of thresholds. Quite complicated to understand. But the higher they are, the more ticks are labelled (not exactly so. To be more accurate, but still say it roughly, one of the thresholds is the one under which everything is labelled: "if you have less ticks than a then, label them all. Another, is the one under which only a subset (controlled by other parameters) of the ticks are labelled. Over both, only power of the base are labelled).

So, all together

import matplotlib.pyplot as plt
from matplotlib.ticker import LogLocator, LogFormatterSciNotation
fig, ax = plt.subplots()
ax.set_yscale("log")
ax.get_yaxis().set_major_locator(LogLocator(subs=(1,2,3,4,5,6,7,8,9,)))
ax.get_yaxis().set_major_formatter(LogFormatterSciNotation(base=10, minor_thresholds=(1000,1000), labelOnlyBase=False))
ax.plot([1,2,3,4,5], [4500, 4000, 1000, 500, 450])
plt.show()

(1000,1000) here is a "don't try to understand and just put insanely high values" parameters :D. I would have used (np.inf, np.inf) if numpy was imported. But that would be 1 line more.

Result:

enter image description here

chrslg
  • 9,023
  • 5
  • 17
  • 31