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$
0

2 Answers 2

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.

$\endgroup$
3
  • $\begingroup$ Nice answer. I would suggest to use a defined SeedRandom when using RandomVariate so as to make your results replicable? $\endgroup$
    – gwr
    Commented Oct 11, 2017 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
    Commented Oct 11, 2017 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
    Commented Oct 12, 2017 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] *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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