589

I want to plot a graph with one logarithmic axis using matplotlib.

Sample program:

import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]  # exponential
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)

line, = ax.plot(a, color='blue', lw=2)
plt.show()
0

7 Answers 7

684

You can use the Axes.set_yscale method. That allows you to change the scale after the Axes object is created. That would also allow you to build a control to let the user pick the scale if you needed to.

The relevant line to add is:

ax.set_yscale('log')

You can use 'linear' to switch back to a linear scale. Here's what your code would look like:

import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)

line, = ax.plot(a, color='blue', lw=2)

ax.set_yscale('log')

pylab.show()

result chart

9
  • 7
    This method is nice since it works with all sorts of plots (e.g. histograms), not just with "plot" (which is what semilogx/semilogy does) Commented Jul 26, 2009 at 0:18
  • 19
    I came here looking for how to use an axis for powers of two: pylab.gca().set_xscale('log',basex=2)
    – zje
    Commented Apr 12, 2012 at 20:16
  • 77
    Matplotlib has semilogy(). Furthermore, it is easier to directly use pyplot.yscale() than to use ax.set_yscale('log'), as there is no need to get the ax object (which is not always immediately available). Commented Feb 28, 2013 at 5:43
  • 7
    If you want log scales on both axes, try loglog() or on x-axis only try semilogx()
    – drevicko
    Commented Jun 28, 2013 at 7:00
  • 17
    @EOL I would advise the opposite. It is better to use an explicit ax object that to use pyplot which only might apply to the Axes you want it to.
    – tacaswell
    Commented May 3, 2016 at 4:08
404

First of all, it's not very tidy to mix pylab and pyplot code. What's more, pyplot style is preferred over using pylab.

Here is a slightly cleaned up code, using only pyplot functions:

from matplotlib import pyplot

a = [ pow(10,i) for i in range(10) ]

pyplot.subplot(2,1,1)
pyplot.plot(a, color='blue', lw=2)
pyplot.yscale('log')
pyplot.show()

The relevant function is pyplot.yscale(). If you use the object-oriented version, replace it by the method Axes.set_yscale(). Remember that you can also change the scale of X axis, using pyplot.xscale() (or Axes.set_xscale()).

Check my question What is the difference between ‘log’ and ‘symlog’? to see a few examples of the graph scales that matplotlib offers.

1
  • 21
    pyplot.semilogy() is more direct. Commented Feb 28, 2013 at 5:43
114

if you want to change the base of logarithm, just add:

plt.yscale('log',base=2) 

Before Matplotlib 3.3, you would have to use basex/basey as the bases of log

78

You simply need to use semilogy instead of plot:

from pylab import *
import matplotlib.pyplot  as pyplot
a = [ pow(10,i) for i in range(10) ]
fig = pyplot.figure()
ax = fig.add_subplot(2,1,1)

line, = ax.semilogy(a, color='blue', lw=2)
show()
1
  • 11
    There is also semilogx. If you need log on both axes, use loglog
    – drevicko
    Commented Jan 19, 2015 at 0:24
13

I know this is slightly off-topic, since some comments mentioned the ax.set_yscale('log') to be "nicest" solution I thought a rebuttal could be due. I would not recommend using ax.set_yscale('log') for histograms and bar plots. In my version (0.99.1.1) i run into some rendering problems - not sure how general this issue is. However both bar and hist has optional arguments to set the y-scale to log, which work fine.

references: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.bar

http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist

11

So if you are simply using the unsophisticated API, like I often am (I use it in ipython a lot), then this is simply

yscale('log')
plot(...)

Hope this helps someone looking for a simple answer! :).

0
0

There are a few methods given on this page (semilogx, semilogy, loglog) but they all do the same thing under the hood, which is to call set_xscale('log') (for x-axis) and set_yscale('log') (for y-axis). Moreover, plt.yscale/plt.scale are functions in the state-machine, which make calls to set_yscale/set_xscale on the current Axes objects. Even for bar-charts (and histograms too since they are just bar-charts), the log=True parameter makes calls to set_yscale('log')/set_xscale('log') depending on the bar orientation.

So it doesn't matter which one you use, they all end up calling the same method anyway. By the way, on top of being able to choose the base of the log, you can also set minor tick locations in the same function call (using subs kwarg).

data = np.random.choice(np.logspace(-0.5, 1, base=20), 10)
plt.plot(data)
plt.yscale('log', base=10, subs=[10**x for x in (0.25, 0.5, 0.75)], nonpositive='mask')
#                          ^^^ <-- 3 equal-spaced minor ticks       ^^^^ mask invalid values

result