Fitting lognormal and normal in one plot

Viewed 104

I have to fit lognormal and normal to my data on one plot in order to compare them. I was able to fit normal to my data which looks like the figure below. I'm having a hard time adding the fitted lognormal enter image description here

Here is my code:

   mu, std = st.norm.fit(data)
   plt.hist(data, 50, density=True, facecolor='orange', alpha=0.75)
   xmin, xmax  = plt.xlim()
   x = np.linspace(xmin,xmax,100)
   p = st.norm.pdf(x, mu, std)
   plt.plot(x, p, 'k', linewidth=1.5)
   plt.show()
1 Answers

stats.lognorm works similar to stats.norm, but 3 parameters are used. Having 3 parameters makes the distribution harder to fit, and often loc is given an initial guess of zero. Without such an initial guess, the fit is often quite poor. Note that instead of a guess, also a fixed loc can be set as lognorm.fit(data, floc=0).

import numpy as np
from scipy import stats as st
import matplotlib.pyplot as plt

data = 60 + (np.random.randn(50, 200)+0.2).cumsum(axis=0).ravel()

lshape, lloc, lscale = st.lognorm.fit(data, loc=0)
mu, std = st.norm.fit(data)
plt.hist(data, 50, density=True, facecolor='orange', alpha=0.75)

xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 500)
plt.plot(x, st.norm.pdf(x, mu, std), color='dodgerblue', linewidth=1.5, label='gaussian normal')
plt.plot(x, st.lognorm.pdf(x, lshape, loc=lloc, scale=lscale), color='limegreen', linewidth=1.5, label='lognormal')
plt.legend()
plt.autoscale(enable=True, axis='x', tight=True)
plt.show()

example plot

PS: To try out Paul H's library which can be installed with pip install paramnormal:

import paramnormal

lognorm_params = paramnormal.lognormal.fit(data)
plt.plot(x, paramnormal.lognormal.from_params(lognorm_params).pdf(x))

At first sight, for these example data it gives the same curve (but with different parametrization) as st.lognorm.fit(data, loc=0).

Related