Jim
Jim

Reputation:

Plot logarithmic axes

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()

Upvotes: 604

Views: 1517117

Answers (7)

Mathieu
Mathieu

Reputation: 7541

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

Upvotes: 696

cottontail
cottontail

Reputation: 23111

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

Upvotes: 1

Dawid
Dawid

Reputation: 1555

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

Upvotes: 117

crazy2be
crazy2be

Reputation: 2252

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! :).

Upvotes: 13

Denilson S&#225; Maia
Denilson S&#225; Maia

Reputation: 49367

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.

Upvotes: 406

user3465408
user3465408

Reputation: 209

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

Upvotes: 13

Scott McCammon
Scott McCammon

Reputation: 1905

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()

Upvotes: 78

Related Questions