LogNormal-Distribution - how to set mu and sigma

Hey there! I’m trying to draw random numbers from a Log-Normal distribution with a given mean and standard-deviation. As far as i know, the LogNormal(\mu \sigma) lets you set the mean and standard deviation of the distribution. I am not really clear however, if I should feed the function with log(valuex) or just with value x, for either mu or sigma. I’m not so sure, what the documentation tries to explain (maybe it’s lack of maths…). it states:

LogNormal(mu, sig) # Log-normal distribution with log-mean mu and scale sig

So how do I do this? Say, I want to use x as mean and y as scale, do I draw from LogNormal(log(x), y)? In R I would use the log(x), but how about Julia? Thanks so much!

You have to calculate μ if you want a given mean. See the wikipedia page of about the lognormal. For example, you could do

using Distributions

μ_for_mean(m, σ) = log(m) - σ^2/2

m = 2
σ = 0.5
d = LogNormal(μ_for_mean(m, σ), σ)

mean(d) ≈ m                     # voila
2 Likes

Thanks! That answers my question nicely :slight_smile: one of topic question: how did you make the mu ign a mu sign? I tried \mu but that didn’t work… Thanks again!

Press [TAB] after \mu in the REPL (I actually made it in Emacs though, using company-math). See unicode input.

1 Like

Thanks! :slight_smile:

Notice that σ is not the standard deviation of the LogNormal distribution, e.g.

julia> std(LogNormal(0,1))
2.1611974158950877

so if your inputs are the mean and standard deviation then the problem of finding μ and σ is a bit harder since there is no closed form solution. I actually had to do this recently and ended up doing something like

julia> f = (θ, lm) -> norm([θ[1] + θ[2]^2/2 - lm[1], log(exp(θ[2]^2) - 1) + 2*θ[1] + θ[2]^2 - lm[2]])^2
(::#71) (generic function with 1 method)

julia> LogNormal(Optim.minimizer(optimize(t -> f(t, log.([1, 1])), [1.0, 1.0], BFGS()))...) |> t -> (mean(t), std(t))
(1.0000000001643707, 1.000000000094841)

Notice that solving for the logarithm of the mean and standard deviations works much better that solving for the untransformed variables.

2 Likes

Thanks so much! I ended up using the definitions given for μ and σ on Wikipedia (https://en.wikipedia.org/wiki/Log-normal_distribution), like follows:

ParVal=readdlm(“StandardScenario_alpha4_2.txt”)
hind=Array{Float64,1}(ParVal[2:end, 4])
gind=Array{Float64,1}(ParVal[2:end, 5])
uniquehind=unique(hind)
uniquegind=unique(gind)
meanhindunique=mean(uniquehind)
meangindunique=mean(uniquegind)
sthindunique=std(uniquehind)
vargindunique=var(uniquegind)
σgindunique=sqrt(log(vargindunique/meangindunique^2+1))
μgindunique=log(meangindunique) - σgindunique^2/2

The .txt contains the data I’m using the get the distribution, I didn’t think it would be necessary to give mock-data so you can copy what I did, but rather to illustrate, how I calculated μ and σ.
For me, it seems similar to what you did (?), but I’m not familiar with the Optim.minimizer function you used. However, my supervisor agreed on my calculation, so I guess, for my purposes it works.
Thank you anyways! :slight_smile:

1 Like

Ha. Thanks for the correction. Indeed that is the closed form solution for σ and μ.

2 Likes

Yeah for Wikipedia and an interest in maths :wink:

Hello from the future. If you know both the mean and standard deviation you want, this function does the trick:

using Distributions

function myLogNormal(m,std)
    γ = 1+std^2/m^2
    μ = log(m/sqrt(γ))
    σ = sqrt(log(γ))

    return LogNormal(μ,σ)
end

I know the transformation already appeared in your later comments, but I thought it’s worth it to post some clear code.

3 Likes

This seems like it would be a worthwhile addition to Distributions.jl, don’t you think? A super easy PR it seems.

1 Like

It would be interesting to have a wrapper for moments, and then utilize the fit framework, eg have something like

fit(LogNormal, Moments(m, std))

do the above.

4 Likes

Yes, that would be really neat to include this!

Perfect! Much clearer this way :slight_smile:

Does Moments exist in Distributions package?

You may be interested in MeasureTheory.jl

Cc @cscherrer

1 Like

Thanks @EvoArt ! I don’ know if this is what you have in mind, but one important design point about MeasureTheory is to make it easy to work with different parameterizations. The setup is that a ParameterizedMeasure is just a struct with a NamedTuple field, and we use KeywordCalls.jl for dispatch.

So for example, we can have a LogNormal(μ,σ) set up to work exactly like Distributions, and also have LogNormal(moments=(m,std)) available.

To be fair, Distributions could be adapted to do this as well, but in that case it would probably just build a LogNormal with the standard parameterization. The advantage of the MeasureTheory approach is that we allow different parameterizations to be used directly, without conversion to some standard form. Here that doesn’t help so much (I think you’d probably want to convert it anyway), but in some cases it can make things much more efficient.

4 Likes

@John_Coppola see this new package also GitHub - bgctw/DistributionFits.jl: Extension of Distributions.jl allows specifying distributions by aggregate statistics #1296

1 Like