By Dax Feliz


2012-09-26 19:12:53 8 Comments

I am trying to fix how python plots my data.

Say

x = [0,5,9,10,15]

and

y = [0,1,2,3,4]

Then I would do:

matplotlib.pyplot.plot(x,y)
matplotlib.pyplot.show()

and the x axis' ticks are plotted in intervals of 5. Is there a way to make it show intervals of 1?

10 comments

@Gary Steele 2019-11-02 21:21:01

if you just want to set the spacing a simple one liner with minimal boilerplate:

plt.gca().xaxis.set_major_locator(plt.MultipleLocator(1))

also works easily for minor ticks:

plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))

a bit of a mouthfull, but pretty compact

@robochat 2013-11-14 08:38:42

Another approach is to set the axis locator:

import matplotlib.ticker as plticker

loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)

There are several different types of locator depending upon your needs.

Here is a full example:

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)
plt.show()

@Chris Fonnesbeck 2014-02-05 17:02:28

This does not work as expected. Specifically, when using dates, it does not use the appropriate dates.

@robochat 2014-03-20 13:06:27

When using dates, you should use the methods in the matplotlib.dates module. For example matplotlib.dates.AutoDateLocator()

@Pablo Suau 2016-07-08 13:58:52

It worked as expected for me, with dates. This solution is much easier than the accepted one.

@Greenstick 2017-07-28 20:55:08

Here's a pure python implementation of the desired functionality that handles any numeric series (int or float) with positive, negative, or mixed values:

def computeTicks (x, step = 5):
    """
    Computes domain with given step encompassing series x
    @ params
    x    - Required - A list-like object of integers or floats
    step - Optional - Tick frequency
    """
    import math as Math
    xMax, xMin = Math.ceil(max(x)), Math.floor(min(x))
    dMax, dMin = xMax + abs((xMax % step) - step) + (step if (xMax % step != 0) else 0), xMin - abs((xMin % step))
    return range(dMin, dMax, step)

Sample Output:

# Negative to Positive
series = [-2, 18, 24, 29, 43]
print(list(computeTicks(series)))

[-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

# Negative to 0
series = [-30, -14, -10, -9, -3, 0]
print(list(computeTicks(series)))

[-30, -25, -20, -15, -10, -5, 0]

# 0 to Positive
series = [19, 23, 24, 27]
print(list(computeTicks(series)))

[15, 20, 25, 30]

# Floats
series = [1.8, 12.0, 21.2]
print(list(computeTicks(series)))

[0, 5, 10, 15, 20, 25]

# Step – 100
series = [118.3, 293.2, 768.1]
print(list(computeTicks(series, step = 100)))

[100, 200, 300, 400, 500, 600, 700, 800]

And Sample Usage:

import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(computeTicks(x))
plt.show()

@Piyush Gupta 2017-06-30 07:33:23

xmarks=[i for i in range(1,length+1,1)]

plt.xticks(xmarks)

This worked for me

if you want ticks between [1,5] (1 and 5 inclusive) then replace

length = 5

@Neal 2017-07-21 13:30:39

fyi, you could simply write xmarks = range(1, length+1, 1). pretty sure the list comprehension is redundant.

@glopes 2016-04-15 11:46:09

In case anyone is interested in a general one-liner, simply get the current ticks and use it to set the new ticks by sampling every other tick.

ax.set_xticks(ax.get_xticks()[::2])

@Ryszard Cetnarski 2018-09-20 14:54:17

This is the only generalisable answer for different tick types (str, float, datetime)

@user2839288 2019-06-22 22:04:34

Remove non-integer ticks: ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])

@Iain D 2019-08-30 15:34:20

Lots of detailed solutions above but I agree this is the most concise. You could even extract the length of ax.get_xticks() and set the slicing frequency by this length divided by the number of required ticks.

@Seankala 2019-09-01 06:08:09

I think this is the best answer. Most other answers are too complicated and hard to apply/generalize. Thank you!

@Michel Floyd 2019-10-18 08:42:02

This was very useful, ty.

@Alexei Martianov 2019-10-24 13:06:46

It can only reduce number of sticks, whereas in the question (and mine goal how I found it) was to increase it.

@jthomas 2016-03-25 23:24:37

I like this solution (from the Matplotlib Plotting Cookbook):

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]

tick_spacing = 1

fig, ax = plt.subplots(1,1)
ax.plot(x,y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()

This solution give you explicit control of the tick spacing via the number given to ticker.MultipleLocater(), allows automatic limit determination, and is easy to read later.

@Zelphir Kaltstahl 2016-08-31 09:48:48

A way to do this without calculating the ticks explicitly!

@ImportanceOfBeingErnest 2017-06-23 10:41:19

This is the same answer as this one. It does not make sense to add an identical answer two years later.

@jthomas 2017-06-23 15:17:52

Good catch. I did not recognize them as the same when I posted the answer. Still, I think this presentation is a little easier to understand.

@Steven C. Howell 2018-04-16 19:50:03

The book reference in this answer also provide a helpful source for more information.

@MERose 2019-09-08 14:38:03

This is the same answer as that of robochat, which came three years earlier.

@jthomas 2019-09-09 15:06:01

@MERose, you are correct. Please see comments above for justification on including this answer.

@choldgraf 2015-08-13 20:15:58

This is a bit hacky, but by far the cleanest/easiest to understand example that I've found to do this. It's from an answer on SO here:

Cleanest way to hide every nth tick label in matplotlib colorbar?

for label in ax.get_xticklabels()[::2]:
    label.set_visible(False)

Then you can loop over the labels setting them to visible or not depending on the density you want.

edit: note that sometimes matplotlib sets labels == '', so it might look like a label is not present, when in fact it is and just isn't displaying anything. To make sure you're looping through actual visible labels, you could try:

visible_labels = [lab for lab in ax.get_xticklabels() if lab.get_visible() is True and lab.get_text() != '']
plt.setp(visible_labels[::2], visible=False)

@jolvi 2015-09-22 12:02:32

This is the most simple and generic solution. A tiny adjustment: usually ax.get_xticklabels()[1::2] are the labels to be hidden.

@BCR 2016-02-12 16:12:31

This doesn't work with matplotlib.finance.candlestick2

@choldgraf 2016-02-15 19:57:24

@BCR it could be that some of the xticklabels are just set to '' so that when you loop through them, you're making xticklabels that are empty invisible (which would have no effect on the visualization, but might mean that you aren't pulling the correct labels). You could try: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)

@Deninhos 2015-03-11 13:26:52

I developed an inelegant solution. Consider that we have the X axis and also a list of labels for each point in X.

Example:
import matplotlib.pyplot as plt

x = [0,1,2,3,4,5]
y = [10,20,15,18,7,19]
xlabels = ['jan','feb','mar','apr','may','jun']
Let's say that I want to show ticks labels only for 'feb' and 'jun'
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Good, now we have a fake list of labels. First, we plotted the original version.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Now, the modified version.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

@Tompa 2014-12-17 19:18:45

This is an old topic, but I stumble over this every now and then and made this function. It's very convenient:

import matplotlib.pyplot as pp
import numpy as np

def resadjust(ax, xres=None, yres=None):
    """
    Send in an axis and I fix the resolution as desired.
    """

    if xres:
        start, stop = ax.get_xlim()
        ticks = np.arange(start, stop + xres, xres)
        ax.set_xticks(ticks)
    if yres:
        start, stop = ax.get_ylim()
        ticks = np.arange(start, stop + yres, yres)
        ax.set_yticks(ticks)

One caveat of controlling the ticks like this is that one does no longer enjoy the interactive automagic updating of max scale after an added line. Then do

gca().set_ylim(top=new_top) # for example

and run the resadjust function again.

@unutbu 2012-09-26 19:24:08

You could explicitly set where you want to tick marks with plt.xticks:

plt.xticks(np.arange(min(x), max(x)+1, 1.0))

For example,

import numpy as np
import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()

(np.arange was used rather than Python's range function just in case min(x) and max(x) are floats instead of ints.)


The plt.plot (or ax.plot) function will automatically set default x and y limits. If you wish to keep those limits, and just change the stepsize of the tick marks, then you could use ax.get_xlim() to discover what limits Matplotlib has already set.

start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, stepsize))

The default tick formatter should do a decent job rounding the tick values to a sensible number of significant digits. However, if you wish to have more control over the format, you can define your own formatter. For example,

ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))

Here's a runnable example:

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

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, 0.712123))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
plt.show()

@Corone 2013-10-01 16:41:43

Is there no way to get it to still decide it's own limits, but just change the step size? This method is not very good if the min is something like 3523.232512!

@jthomas 2016-03-26 13:04:42

@Corone, It has been a while since you asked, but I have posted an answer below that allows for easy control of step size while still using automatic bounds determination.

@Alex Willison 2017-05-19 15:23:59

Note that the +1 in plt.xticks(np.arange(min(x), max(x)+1, 1.0)) is required to show the last tick mark.

@unutbu 2017-05-19 16:19:09

Yes, np.arange(start, stop) generates values in the half-open interval [start, stop), including start but excluding stop. So I used max(x)+1 to ensure that max(x) is included.

@WBM 2018-01-10 11:42:58

is there an equivalent for datetime e.g. plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1) ? it seems to only plots the year

@unutbu 2018-01-10 12:51:53

@WBM: You can set both the location and labels using xticks. Alternatively, you could use FuncFormatter to convert floats to string labels. Or if you plot datetime.datetime objects directly (instead of floats) then you could use DateFormatter to format the dates. If this doesn't help or you'd like more clarification, please post a new question.

@jjrr 2018-08-24 16:56:58

@unutbu when I run your code I get TypeError: 'numpy.ndarray' object is not callable ...any idea ? -- I am on matplotlib 2.2.3

@Amir 2019-12-06 12:52:23

it somehow doesnt work when the format of x axis is datetime.

Related Questions

Sponsored Content

15 Answered Questions

[SOLVED] How do I parse XML in Python?

  • 2009-12-16 05:09:24
  • randombits
  • 1185230 View
  • 948 Score
  • 15 Answer
  • Tags:   python xml

10 Answered Questions

[SOLVED] Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?

19 Answered Questions

[SOLVED] How can I use threading in Python?

16 Answered Questions

[SOLVED] How do you change the size of figures drawn with matplotlib?

17 Answered Questions

[SOLVED] How to make a chain of function decorators?

12 Answered Questions

[SOLVED] Calling a function of a module by using its name (a string)

  • 2008-08-06 03:36:08
  • ricree
  • 649410 View
  • 1626 Score
  • 12 Answer
  • Tags:   python object

18 Answered Questions

[SOLVED] Save plot to image file instead of displaying it using Matplotlib

  • 2012-03-08 17:38:10
  • Homunculus Reticulli
  • 1479227 View
  • 1084 Score
  • 18 Answer
  • Tags:   python matplotlib plot

10 Answered Questions

9 Answered Questions

[SOLVED] Proper way to declare custom exceptions in modern Python?

8 Answered Questions

[SOLVED] Hiding axis text in matplotlib plots

Sponsored Content