249

I have too many ticks on my graph and they are running into each other.

How can I reduce the number of ticks?

For example, I have ticks:

1E-6, 1E-5, 1E-4, ... 1E6, 1E7

And I only want:

1E-5, 1E-3, ... 1E5, 1E7

I've tried playing with the LogLocator, but I haven't been able to figure this out.

Trenton McKinney
63.1k41 gold badges169 silver badges210 bronze badges
asked Jul 13, 2011 at 17:08

10 Answers 10

368

Alternatively, if you want to simply set the number of ticks while allowing matplotlib to position them (currently only with MaxNLocator), there is pyplot.locator_params,

pyplot.locator_params(nbins=4)

You can specify specific axis in this method as mentioned below, default is both:

# To specify the number of ticks on both or any single axes
pyplot.locator_params(axis='y', nbins=6)
pyplot.locator_params(axis='x', nbins=10)
Mr. T
12.5k10 gold badges38 silver badges66 bronze badges
answered Nov 16, 2012 at 14:51

12 Comments

This was a great suggestion, also being able to specify pyplot.locator_params(axis = 'x', nbins = 4) (or axis = 'y') made the process really straightforward. Thanks @bgamari!
With log scale, this worked with numticks instead of nbins
This doesn't seem to place the labels where they should be. For example, if the original tick labels are [0, 1, ..., 99] and now one sets nticks=10, then the new sparse labels will be placed ten times as long apart along the axis, i.e. now 1 will sit where 9 was, 2 where 19 was... and 9 where 99 was.
Check your results before trusting this method. @Vim is correct. The tick values will be placed incorrectly.
I got incorrect labeling with this method, but @Katerina's worked as expected.
|
144

To solve the issue of customisation and appearance of the ticks, see the Tick Locators guide on the matplotlib website

ax.xaxis.set_major_locator(plt.MaxNLocator(3))

would set the total number of ticks in the x-axis to 3, and evenly distribute them across the axis.

There is also a nice tutorial about this

Adriaan
18.2k7 gold badges47 silver badges88 bronze badges
answered Apr 15, 2019 at 13:38

6 Comments

Only select first 3 datetime index. when get ax from pandas.DataFrame.plot ax = df.plot()
@Mithril sorry I don't quite understand your comment. Could you please elaborate?
If I have a df ( pandas.DataFrame ) with datetime index [2019年01月01日, ...2019年11月01日], call ax = df.plot() , return a figure object . call ax.xaxis.set_major_locator(plt.MaxNLocator(3)) only show first 3 index [2019年01月01日, 2019年01月02日, 2019年01月03日] .
@Mithril, df.plot() often displays the minor_locator, so you might want to try ax1.xaxis.set_minor_locator(plt.MaxNLocator(3)). Also remember to substitute the 3 for the number of ticks that you want to display. For pandas timeseries I recommend import matplotlib.dates as mdates and run ax.xaxis.set_minor_locator(mdates.MonthLocator(interval = 1)) with ax.xaxis.set_minor_formatter(mdates.DateFormatter('%m-%Y'))
As I had a lot of datapoints to plot, pyplot was printing a lot (>500) ticks per axis. This heavily slowed down the plotting process. By reducing the number of thicks with set_major_locator(5) the plotting process is much faster.
|
111

If somebody still gets this page in search results:

fig, ax = plt.subplots()
plt.plot(...)
every_nth = 4
for n, label in enumerate(ax.xaxis.get_ticklabels()):
 if n % every_nth != 0:
 label.set_visible(False)
answered Apr 8, 2018 at 5:54

2 Comments

In my case with pandas and numerically spaced, this is working as is expected while locator_params(nbins) and plt.MaxNLocator give a strange behavior.
This works for non-numerical x axis labels, which is helpful
27

There's a set_ticks() function for axis objects.

Andre Holzner
18.8k6 gold badges59 silver badges66 bronze badges
answered Jul 13, 2011 at 17:12

5 Comments

This would work if I knew beforehand what ticks I wanted. The example I gave above was only an example. I don't know what the ticks are, I just know I want fewer of them, i.e., every other one.
You could call get_xticks() or get_yticks() first for the axes object, edit as needed, and then pass the list back to set_ticks().
I don't have set_ticks(), but I do have set_xticks() and set_yticks(). These are attributes of axes objects, not axis. Maybe this has changed during the last couple of years.
I am not sure if I should, some people have found your answer useful as is, and just because it is different for me does not mean it is for everybody.
An example would go a long way towards making this answer useful.
15

in case somebody still needs it, and since nothing here really worked for me, i came up with a very simple way that keeps the appearance of the generated plot "as is" while fixing the number of ticks to exactly N:

import numpy as np
import matplotlib.pyplot as plt
f, ax = plt.subplots()
ax.plot(range(100))
ymin, ymax = ax.get_ylim()
ax.set_yticks(np.round(np.linspace(ymin, ymax, N), 2))
answered May 28, 2018 at 16:00

2 Comments

I had to modify the last line slightly in order to get it to return the values as int instead of float: ax.set_yticks(np.linspace(int(ymin), int(ymax), N), 2)
@NickSettje still floats with me!
9

The solution @raphael gave is straightforward and quite helpful.

Still, the displayed tick labels will not be values sampled from the original distribution but from the indices of the array returned by np.linspace(ymin, ymax, N).

To display N values evenly spaced from your original tick labels, use the set_yticklabels() method. Here is a snippet for the y axis, with integer labels:

import numpy as np
import matplotlib.pyplot as plt
ax = plt.gca()
ymin, ymax = ax.get_ylim()
custom_ticks = np.linspace(ymin, ymax, N, dtype=int)
ax.set_yticks(custom_ticks)
ax.set_yticklabels(custom_ticks)
answered Jul 2, 2019 at 21:40

Comments

6

If you need one tick every N=3 ticks :

N = 3 # 1 tick every 3
xticks_pos, xticks_labels = plt.xticks() # get all axis ticks
myticks = [j for i,j in enumerate(xticks_pos) if not i%N] # index of selected ticks
newlabels = [label for i,label in enumerate(xticks_labels) if not i%N]

or with fig,ax = plt.subplots() :

N = 3 # 1 tick every 3
xticks_pos = ax.get_xticks()
xticks_labels = ax.get_xticklabels()
myticks = [j for i,j in enumerate(xticks_pos) if not i%N] # index of selected ticks
newlabels = [label for i,label in enumerate(xticks_labels) if not i%N]

(obviously you can adjust the offset with (i+offset)%N).

Note that you can get uneven ticks if you wish, e.g. myticks = [1, 3, 8].

Then you can use

plt.gca().set_xticks(myticks) # set new X axis ticks

or if you want to replace labels as well

plt.xticks(myticks, newlabels) # set new X axis ticks and labels

Beware that axis limits must be set after the axis ticks.

Finally, you may wish to draw only an arbitrary set of ticks :

mylabels = ['03/2018', '09/2019', '10/2020']
plt.draw() # needed to populate xticks with actual labels
xticks_pos, xticks_labels = plt.xticks() # get all axis ticks
myticks = [i for i,j in enumerate(xticks_labels) if j.get_text() in mylabels]
plt.xticks(myticks, mylabels)

(assuming mylabels is ordered ; if it is not, then sort myticks and reorder it).

answered Nov 13, 2020 at 10:55

2 Comments

there is a little error in the last code block. One of the lines should be written as: myticks = [i for i,j in enumerate(xticks_labels) if j.get_text() in mylabels]
@gtristan Right, fixed, thanks !
3

xticks function auto iterates with range function

start_number = 0

end_number = len(data you have)

step_number = how many skips to make from strat to end

rotation = 90 degrees tilt will help with long ticks

plt.xticks(range(start_number,end_number,step_number),rotation=90)
answered Jun 27, 2021 at 11:02

1 Comment

I came to contribute a range based solution. Your example is much more concise. But to add to it, you can use the shape to get what you want eg plt.xticks(range(0, df.shape[0], 12),rotation=90)
3

if you want 10 ticks:

for y axis: ax.set_yticks(ax.get_yticks()[::len(ax.get_yticks())//10])

for x axis: ax.set_xticks(ax.get_xticks()[::len(ax.get_xticks())//10])

this simply gets your ticks and chooses every 10th of the list and sets it back to your ticks. you can change the number of ticks as you wish.

answered Jan 26, 2023 at 22:32

Comments

-1

When a log scale is used the number of major ticks can be fixed with the following command

import matplotlib.pyplot as plt
....
plt.locator_params(numticks=12)
plt.show()

The value set to numticks determines the number of axis ticks to be displayed.

Credits to @bgamari's post for introducing the locator_params() function, but the nticks parameter throws an error when a log scale is used.

answered Jun 29, 2017 at 9:04

3 Comments

The question and answer are for previous matplotlib, i.e. 1, and you're referring to 2.
I do not think an argument called 'numticks' exists.
Kindly refer the matplotlib doc for numticks @troymyname00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.