109

I created this plot using Matlab

enter image description here

Using matplotlib, the x-axies draws large numbers such as 100000, 200000, 300000. I would like to have something like 1, 2, 3 and a 10^5 to indicate that it's actually 100000, 200000, 300000.

Is there a simple way to create such scale in matplotlib?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Eagle
  • 3,362
  • 5
  • 34
  • 46

4 Answers4

168

Try using matplotlib.pyplot.ticklabel_format:

import matplotlib.pyplot as plt
...
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))

This applies scientific notation (i.e. a x 10^b) to your x-axis tickmarks

Chris
  • 44,602
  • 16
  • 137
  • 156
  • 10
    is it possible to add an offset? (e.g. instead of 0.0, 0.5, 1.0, 1.5, ... and x 10^b it will be 0, 5, 10, 15,... and x 10^{b-1}) – Eagle Jul 20 '12 at 13:20
  • 26
    `ticklabel_format` is also a method for the axes objects, you can try something like `ax.ticklabel_format(style='sci', axis='x', scilimits=(0,0))` – Covich Mar 22 '16 at 10:47
  • How can this work if you have a subplot of, say, 2 plots? – FaCoffee Jul 13 '17 at 11:16
  • 3
    @Eagle sorry, your follow-up question about adding an offset was what I was referring to. my x-axis is `[0.1, 0.2, ...]` and I'd prefer `[1, 2, ...]` with an adjusted exponent. were you able to find a solution for that? – trianta2 Jul 18 '17 at 16:29
  • @Eagle I am also interested in the question trianta2 mentioned – Ben Usman Nov 15 '17 at 03:57
  • For he behaviour asked about here by @trianta2 to have a fixed order of magnititude for the exponent see [this question](https://stackoverflow.com/questions/42656139/set-scientific-notation-with-fixed-exponent-and-significant-digits-for-multiple). – ImportanceOfBeingErnest Mar 18 '18 at 23:01
  • 1
    Hint: use option `UseMathText=True` to get math notation instead of `1e6` – Quastiat Oct 08 '19 at 07:19
  • 1
    Hint full version: `plt.gca().ticklabel_format(useMathText=True)` and magnitude will be displayed as the number 10 – Plo_Koon Apr 15 '20 at 08:10
19

This is not so much an answer to your original question as to one of the queries you had in the body of your question.

A little preamble, so that my naming doesn't seem strange:

import matplotlib
from matplotlib import rc
from matplotlib.figure import Figure
ax = self.figure.add_subplot( 111 )

As has been mentioned you can use ticklabel_format to specify that matplotlib should use scientific notation for large or small values:

ax.ticklabel_format(style='sci',scilimits=(-3,4),axis='both')

You can affect the way that this is displayed using the flags in rcParams (from matplotlib import rcParams) or by setting them directly. I haven't found a more elegant way of changing between '1e' and 'x10^' scientific notation than:

ax.xaxis.major.formatter._useMathText = True

This should give you the more Matlab-esc, and indeed arguably better appearance. I think the following should do the same:

rc('text', usetex=True)
lskrinjar
  • 5,483
  • 7
  • 29
  • 54
Weir_Doe
  • 533
  • 4
  • 11
12

The scalar formatter supports collecting the exponents. The docs are as follows:

class matplotlib.ticker.ScalarFormatter(useOffset=True, useMathText=False, useLocale=None) Bases: matplotlib.ticker.Formatter

Tick location is a plain old number. If useOffset==True and the data range is much smaller than the data average, then an offset will be determined such that the tick labels are meaningful. Scientific notation is used for data < 10^-n or data >= 10^m, where n and m are the power limits set using set_powerlimits((n,m)). The defaults for these are controlled by the axes.formatter.limits rc parameter.

your technique would be:

from matplotlib.ticker import ScalarFormatter
xfmt = ScalarFormatter()
xfmt.set_powerlimits((-3,3))  # Or whatever your limits are . . .
{{ Make your plot }}
gca().xaxis.set_major_formatter(xfmt)

To get the exponent displayed in the format x10^5, instantiate the ScalarFormatter with useMathText=True.

After Image

You could also use:

xfmt.set_useOffset(10000)

To get a result like this:

enter image description here

jwalton
  • 5,286
  • 1
  • 18
  • 36
Carl F.
  • 6,718
  • 3
  • 28
  • 41
8

I find the simple solution

pylab.ticklabel_format(axis='y',style='sci',scilimits=(1,4))
akjoshi
  • 15,374
  • 13
  • 103
  • 121
cunzhang
  • 197
  • 2
  • 4