Solved – Deriving mu and sigma from the log normal distribution given the expected mean and variance

distributionslognormal distributionmonte carlosampling

I'm attempting to sample from the log normal distribution using numbers.js.

Looking at Wikipedia it looks like I need to solve for mu and sigma. So if I want the mean of the samples to be 10 then I need to solve (Passing in the copied wikipedia markup):

$$10 = {\displaystyle \exp \left(\mu +{\frac {\sigma ^{2}}{2}}\right)}$$

and

$$5 = {\displaystyle [\exp(\sigma ^{2})-1]\exp(2\mu +\sigma ^{2})}$$

I'm I on the right path and is there an online calculator or other simple way (Spreadsheet / Libreoffice) to solve these equations?

Found this in Julia Disourse server:

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

    return LogNormal(μ,σ)
end

Does it look about right?

Update

Tried out this Javascript version (Generally the numbers look a lot more believable):

    var numbers = require('numbers');
    function params(m,std) {
        let γ = 1+std^2/m^2
        let μ = Math.log(m/Math.sqrt(γ))
        let σ = Math.sqrt(Math.log(γ))
        let n = numbers.random.distribution.logNormal(100, μ, σ);
        console.log(n);;   

        return {mu: μ, sigma: σ};
    }

However when calculating stats from a sampled array the standard deviation looks like it's too large:

    let p = params(10,5);

    console.log(p);
    let n = numbers.random.distribution.logNormal(1000000, p.mu, p.sigma);
    console.log('mathjs std: ', mathjs.std(n));
    console.log('mathjs mean: ', mathjs.mean(n));

LOGGED RESULT:

    { mu: 1.6094379124341003, sigma: 1.1774100225154747 }
    mathjs std:  17.475889552862462
    mathjs mean:  9.972682726284187

Best Answer

Begin by logging both equations

\begin{align} \mu+\sigma^2/2&=\ln{10}\\ \ln{(e^{\sigma^2}-1)}+2\mu+\sigma^2&=\ln {5} \end{align}

You can substitute line 1 into line 2:

\begin{align} \ln{(e^{\sigma^2}-1)}+2\ln{10}&=\ln{5}\\ \ln{(e^{\sigma^2}-1)}&=\ln {5}-2\ln{10}\\ e^{\sigma^2}&=e^{\ln {5}-2\ln{10}}+1=5/10^2+1\\ \sigma^2&=\ln{\big(5/10^2+1\big)}\\ \sigma&\approx0.2209 \end{align}

So: $\mu=\ln{10}-\sigma^2/2\approx2.278$

In R:

set.seed(1)
m <- 10
v <- 5
(sigma <- sqrt(log(v / m ^ 2 + 1)))
# [1] 0.220885
(mu <- log(m) - sigma ^ 2 / 2)
# [1] 2.27819
mean(x <- rlnorm(5e5, mu, sigma))
# [1] 9.998877
var(x)
# [1] 4.994411