Matplotlib logarithmic scale on histograms

Import directive

In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

Plot function

In [2]:
def plot(data,
         bins=None,
         num_bins=30,
         logx=False,
         logy=False,
         linear_xlabel_style=None,   # 'sci'
         linear_ylabel_style=None):  # 'sci'
    
    fig, axis = plt.subplots()

    if logx:
        # Setup the logarithmic scale on the X axis
        vmin = np.log10(min(data))
        vmax = np.log10(max(data))
        
        # Make a range from 10**vmin to 10**vmax
        bins = np.logspace(vmin, vmax, num_bins if num_bins is not None else 50)
    elif num_bins is not None:
        bins = np.linspace(min(data), max(data), num_bins)
    else:
        # bins=[0, 1, 2, 3] make the following bins: [0,1[, [1,2[ and [2,3]
        # For more information, see:
        # - https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html
        # - http://stackoverflow.com/questions/15177203/how-is-the-pyplot-histogram-bins-interpreted
        bins = list(range(math.floor(min(data)), math.floor(max(data)) + 2))
    
    axis.hist(data,
              bins,
              log=logy)
    
    #axis.plot([0, 70000], [0, 70000], 'r--')
    
    if logy:
        # Don't put 0 otherwise bins at 1 will be invisible
        axis.set_ylim(ymin=0.1)
    else:
        axis.set_ylim(ymin=0)
    
    # Log scale and tick label format
    if logx:
        axis.set_xscale("log")               # Activate log scale on X axis
    elif linear_xlabel_style == 'sci':
        axis.ticklabel_format(style='sci', axis='x', scilimits=(0,0))

    if (not logy) and (linear_ylabel_style == 'sci'):
        axis.ticklabel_format(style='sci', axis='y', scilimits=(0,0))
        
    plt.show()

Power distribution

In [3]:
data = np.random.power(a=2.0, size=1000000) * 70000
In [4]:
plot(data)
In [5]:
plot(data,
     logx=True)
In [6]:
plot(data,
     logy=True)
In [7]:
plot(data,
     logx=True,
     logy=True)