Logarithmic y-axis bins in python

79,938

Solution 1

try

plt.yscale('log', nonposy='clip')

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

The issue is with the bottom of bars being at y=0 and the default is to mask out in-valid points (log(0) -> undefined) when doing the log transformation (there was discussion of changing this, but I don't remember which way it went) so when it tries to draw the rectangles for you bar plot, the bottom edge is masked out -> no rectangles.

Solution 2

np.logspace returns bins in [1-10], logarithmically spaced - in my case xx is a npvector >0 so the following code does the trick

logbins=np.max(xx)*(np.logspace(0, 1, num=1000) - 1)/9
hh,ee=np.histogram(xx, density=True, bins=logbins)

Solution 3

The hist constructor accepts the log parameter.
You can do this:

plt.hist(data, bins=bins, log=True)
Share:
79,938
mannaroth
Author by

mannaroth

Astrophysicist.

Updated on July 09, 2022

Comments

  • mannaroth
    mannaroth almost 2 years

    I'm trying to create a histogram of a data column and plot it logarithmically (y-axis) and I'm not sure why the following code does not work:

    import numpy as np
    import matplotlib.pyplot as plt
    data = np.loadtxt('foo.bar')
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.hist(data, bins=(23.0, 23.5,24.0,24.5,25.0,25.5,26.0,26.5,27.0,27.5,28.0))
    ax.set_xlim(23.5, 28)
    ax.set_ylim(0, 30)
    ax.grid(True)
    plt.yscale('log')
    plt.show()
    

    I've also tried instead of plt.yscale('log') adding Log=true in the plt.hist line and also I tried ax.set_yscale('log'), but nothing seems to work. I either get an empty plot, either the y-axis is indeed logarithmic (with the code as shown above), but there is no data plotted (no bins).

  • mannaroth
    mannaroth almost 11 years
    Thanks for the answer. The solution you proposed solved the disappearing bars, but another "bug" then surfaced: all the labels of the y-logarithmic axis were plotted on top of each other. This last problem was solved by commenting the "ax.set_ylim(0, 30)" line.
  • tacaswell
    tacaswell almost 11 years
    yes, because the 0 in the limit is clipped to some very small number so you have an unreasonable number of decades. use ax.set_ylim(1, 30) instead.