6

I am trying to reduce the number of axis ticks in subplots (each axis different values, so I can't set the ticks manually), but other answers such as this or this don't work. My syntax for creating the figure is standard, as follows:

fig = plt.figure(figsize=(7,9))
ax = fig.add_subplot(8,2,i+1) # I am plotting in a much larger loop, but I don't think there is anything wrong with the loop, because everything else (axis limits, labels, plotting itself...) works fine.

and to reduce the number of yticks, I tried

ax = plt.locator_params(nbins=4, axis='y')

which raised the error TypeError: set_params() got an unexpected keyword argument 'nbins'

and I tried

ax.yaxis.set_major_locator(plt.MaxNLocator(4))

which gave the error AttributeError: 'NoneType' object has no attribute 'yaxis'

I don't understand why my subplot is considered to be a NoneType. I suspect this is the core of the problem, but all examples that I saw have the same structure, i.e.

fig = plt.figure()
ax = fig.add_subplot(111)
ax.yaxis.set_major_locator(plt.MaxNLocator(4))

and it should work. So why is my ax NoneType?

Community
  • 1
  • 1
durbachit
  • 4,626
  • 10
  • 36
  • 49
  • Yes, `fig = plt.figure(); ax = fig.add_subplot(111); ax.yaxis.set_major_locator(plt.MaxNLocator(3))` should work and it does in my case. Are those the only lines in the script? How did you import pyplot? – ImportanceOfBeingErnest Nov 10 '16 at 08:07
  • Weird, in this case there must be something invisibly wrong with the stuff that I am actually plotting, which messes up the ax object. Imported pyplot the standard way, `import matplotlib.pyplot as plt` but no, these are not the only lines in the script. There is a lot of data reading in and processing in order to plot them. But even if I comment everything else out, I still get the same error. – durbachit Nov 11 '16 at 02:17
  • Could it be the problem that I create these subplots in a loop? `for i,col in enumerate(column_list): ax = fig.add_subplot(8,2,i+1)` – durbachit Nov 11 '16 at 02:18

1 Answers1

2

The problem is the line:

ax = plt.locator_params(nbins=4, axis='y')

locator_params does not return an Axes instance (in fact it doesn't return anything), so on this line you are reassigning ax to be None.

I think you want to change it to:

ax.locator_params(nbins=4, axis='y')

and then it should all work ok.

tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • In this case I get the `AttributeError: 'NoneType' object has no attribute 'locator_params'` – durbachit Nov 11 '16 at 02:09
  • 1
    In that case, you need to share more of your code, as you must have another command which is modifying `ax` before you get to that line – tmdavison Nov 11 '16 at 02:44
  • 1
    I see, a part of the problem was that I was saying `ax = plt.plot(...)` instead of `ax.plot(...)` - now changing this, `ax.yaxis.set_major_locator(plt.MaxNLocator(7))` doesn't throw the error and even plots something, although it doesn't give the number of ticks I want. `ax.locator_params(nbins=4, axis='y')` still gives the same error. – durbachit Nov 11 '16 at 03:46
  • Oh, I have a suspicion: the MaxNLocator doesn't work on a log scale, does it? – durbachit Nov 11 '16 at 05:21
  • 3
    `MaxNLocator` shouldn't work on a logscale, correct. But it shouln't throw an error either, it will just not show any tickmarks. You can use the `LogLocator(base=10.0, subs=[1.0], numdecs=4, numticks=15)` instead. – ImportanceOfBeingErnest Nov 11 '16 at 08:19
  • Unfortunately, both methods lead to a miss-alignment of the labels and the figure. I.e. only the top of the labels are used and aligned over the whole figure. Instead, every Xth label should be used. – Soerendip Aug 06 '20 at 20:39