0
$\begingroup$

I would like to fit a LogNormalDistribution[μ,σ] based on some data that I have. Roughly speaking, would I need to take the Log of these data's y-values before calculating the mean and standard deviation in order to determine $\mu$ and $\sigma$ above, or can I calculate $\mu$ and $\sigma$ directly from the data and supply these values to Mathematica's LogNormalDistribution-function?

Thanks.

$\endgroup$
6
$\begingroup$

Update: Added in @gwr 's suggestion about using SeedRandom so the one can obtain exactly the same answers as below.

It's not clear that your question has anything to do with Mathematica but rather should you use maximum likelihood or method of moments (which would be best asked at CrossValidated).

Consider a random sample from a log normal distribution:

SeedRandom[12345]
n = 100;
data = RandomVariate[LogNormalDistribution[1, 0.3], n];

One can use the FindDistributionParameters function or brute force it:

(* Maximum likelihood *)
FindDistributionParameters[data, LogNormalDistribution[μ, σ]] 
{μ -> 0.940761, σ -> 0.291374}

(* Maximum likelihood the direct way *)
Mean[Log[data]]
(* 0.940761 *)
StandardDeviation[Log[data]] ((n - 1)/n)^0.5
(* 0.291374 *)

If you don't want to take the logs of the data, then consider the method of moments where you equate the sample moments to the population moments:

$$E(X)=e^{\mu+\sigma^2/2}$$ $$V(X)=e^{2\mu} e^{\sigma^2}(e^{\sigma^2}-1)$$

(* Method of moments *)
FindDistributionParameters[data, LogNormalDistribution[μ, σ], ParameterEstimator -> "MethodOfMoments"]
(* {μ -> 0.939427, σ -> 0.298547} *)

(* Method of moments the direct way *)
FindRoot[{Mean[data] == Exp[μ + σ^2/2], 
  Variance[data] (n - 1)/n == Exp[2 μ] Exp[σ^2] (Exp[σ^2] - 1)},
  {{μ, Mean[Log[data]]}, {σ, StandardDeviation[data]}}]
(* {μ -> 0.939427, σ -> 0.298547} *)

As to which method (or some other method) is best, that would be a question for CrossValidated.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Nice answer. I would suggest to use a defined SeedRandom when using RandomVariate so as to make your results replicable? $\endgroup$ – gwr Oct 11 '17 at 18:07
  • 1
    $\begingroup$ @gwr Good suggestion! In fact, I thing I might open a question about that: Does the same SeedRandom selection get the same sequence of random numbers among versions of Mathematica and among different operating systems. $\endgroup$ – JimB Oct 11 '17 at 18:53
  • $\begingroup$ I just tested RandomVariate[ NormalDistribution[ ] , 1000 ] given the same seed: Versions 10.4, 11.1.1, and 11.2 give the exact same values, which I confirmed by using Hash. $\endgroup$ – gwr Oct 12 '17 at 14:38
4
$\begingroup$

There are slight variations in the distribution obtained depending on the specific approach taken

Generating data

SeedRandom[0]

data = RandomVariate[LogNormalDistribution[3, 1.5], 1000];

FindDistribution will conclude that this data has a LogNormalDistribution

(dist1 = FindDistribution[data]) // InputForm

(* LogNormalDistribution[
 2.875997585829534, 1.5560895409245938] *)

However, if you specify that it is a LogNormalDistribution

(dist2 = FindDistribution[data, 
    TargetFunctions -> {LogNormalDistribution}]) // InputForm

(* LogNormalDistribution[
 2.904567956011853, 1.5056882462684804] *)

To force a fit to a LogNormalDistribution using FindDistributionParameters

(dist4 = LogNormalDistribution[m, s] /. 
    FindDistributionParameters[data, 
     LogNormalDistribution[m, s]]) // InputForm

(* LogNormalDistribution[
 2.904567990925176, 1.505688384471444] *)

This is equivalent to

(dist5 = LogNormalDistribution[m, s] /. 
    FindDistributionParameters[Log[data], 
     NormalDistribution[m, s]]) // InputForm

(* LogNormalDistribution[
 2.904567990925176, 1.505688384471444] *)

dist4 === dist5

(* True *)

Using the Mean and StandardDeviation of the Log of the data

(dist6 = LogNormalDistribution @@ (#[Log[data]] & /@ {Mean, 
       StandardDeviation})) // InputForm

(* LogNormalDistribution[
 2.904567990925176, 1.5064417937677634] *)

Using TransformedDistribution on the Log of the data

(dist7 = TransformedDistribution[E^x, 
    x \[Distributed] FindDistribution[Log[data]]]) // InputForm

(* LogNormalDistribution[
 2.904567990925176, 1.5056883844714437] *)

(dist8 = TransformedDistribution[E^x, 
    x \[Distributed] 
     FindDistribution[Log[data], 
      TargetFunctions -> {NormalDistribution}]]) // InputForm

(* LogNormalDistribution[
 2.904567941143856, 1.505688383284438] *)
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.