Skip to content Skip to sidebar Skip to footer

How To Fit A Log-normal Distribution With Scipy?

I want to fit the log-normal parameters mu and sigma to an existing (measured) log-normal distribution. The measured log-normal distribution is defined by the following x and y arr

Solution 1:

It works out of the box with curve_fit if you scale the data. I am not sure if scaling and re-scaling makes sense, though. (this seems to confirm the ansatz)

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit

def log_fit( x, a, mu, sigma ):
    return a / x * 1. / (sigma * np.sqrt( 2. * np.pi ) ) * np.exp( -( np.log( x ) - mu )**2 / ( 2. * sigma**2 ) )

pp = np.argmax( y )

yM = y[ pp ]
xM = x[ pp ]

xR = x/xM
yR = y/yM
print xM, yM
sol, err = curve_fit( log_fit, xR, yR )
print sol
scaledSol = [ yM * sol[0] * xM , sol[1] + np.log(xM), sol[2] ]
print scaledSol
yF = np.fromiter( ( log_fit( xx, *sol ) for xx in xR ), np.float )
yFIR = np.fromiter( (  log_fit( xx, *scaledSol ) for xx in x ), np.float )

fig = plt.figure()
ax = fig.add_subplot( 2,1, 1)
bx = fig.add_subplot( 2,1, 2)
ax.plot( x, y )
ax.plot( x, yFIR )
bx.plot( xR, yR )
bx.plot( xR, yF )
plt.show()

Providing

>>7.499e-0841326812092485.55>> [2.930035250.684368950.87481153]
>> [9080465.32138486, -15.72154211628693, 0.8748115349982701]

and

back-scaled fit and scaled fit

Anyhow, does not really look like that's the fit function.

Solution 2:

My equation search turned up a log-normal shifted type equation giving a good fit to "y = a * exp(-0.5 * ((log(x-d)-b)/c)**2)" with parameters

a =  4.2503194887395930E+13b = -1.6090252935097830E+01c =  6.0250205607650253E-01d = -2.2907054835882373E-08

No scaling needed.

plot

Post a Comment for "How To Fit A Log-normal Distribution With Scipy?"