如何使用Mu和Sigma在Python中获得对数正态分布?

时间:2012-01-15 15:48:00

标签: python statistics scipy

我一直在尝试使用lognormal获取Scipy发布的结果。我已经拥有Mu和Sigma,所以我不需要做任何其他准备工作。如果我需要更具体(并且我试图利用我对统计数据的有限知识),我会说我正在寻找累积函数(在Scipy下的cdf)。问题是我无法弄清楚如何只用0-1的平均值和标准差来做到这一点(即返回的答案应该是0-1的答案)。我也不确定 dist 采用哪种方法,我应该用它来得到答案。我已经尝试阅读文档并查看SO,但相关问题(如thisthis)似乎没有提供我正在寻找的答案。

以下是我正在使用的代码示例。感谢。

from scipy.stats import lognorm
stddev = 0.859455801705594
mean = 0.418749176686875
total = 37
dist = lognorm.cdf(total,mean,stddev)

更新

经过一些工作和一些研究后,我得到了更多。但我仍然得到了错误的答案。新代码如下。根据R和Excel,结果应该是 .7434 ,但这显然不是正在发生的事情。我缺少一个逻辑缺陷吗?

dist = lognorm([1.744],loc=2.0785)
dist.cdf(25)  # yields=0.96374596, expected=0.7434

更新2: 工作lognorm实现,产生正确的 0.7434 结果。

def lognorm(self,x,mu=0,sigma=1):
   a = (math.log(x) - mu)/math.sqrt(2*sigma**2)
   p = 0.5 + 0.5*math.erf(a)
   return p
lognorm(25,1.744,2.0785)
> 0.7434

6 个答案:

答案 0 :(得分:29)

我知道这有点晚了(差不多一年了!)但是我一直在研究scipy.stats中的lognorm函数。很多人似乎对输入参数感到困惑,所以我希望能帮助这些人。上面的例子几乎是正确的,但我发现将平均值设置为位置(“loc”)参数很奇怪 - 这表示cdf或pdf在值大于均值之前没有“起飞”。此外,均值和标准差参数应分别采用exp(Ln(mean))和Ln(StdDev)的形式。

简单地说,参数是(x,shape,loc,scale),参数定义如下:

loc - 没有等价物,这会从您的数据中减去,以便0成为数据范围的下限。

scale - expμ,其中μ是变量对数的平均值。 (在拟合时,通常使用数据日志的样本均值。)

shape - 变量日志的标准差。

我和大多数拥有此功能的人一样经历过同样的挫折,所以我正在分享我的解决方案。请注意,因为如果没有资源汇编,解释就不那么清楚了。

有关详细信息,我发现这些来源很有用:

这是一个例子,取自@ serv-inc的答案,发布在本页here:

import math
from scipy import stats

# standard deviation of normal distribution
sigma = 0.859455801705594
# mean of normal distribution
mu = 0.418749176686875
# hopefully, total is the value where you need the cdf
total = 37

frozen_lognorm = stats.lognorm(s=sigma, scale=math.exp(mu))
frozen_lognorm.cdf(total) # use whatever function and value you need here

答案 1 :(得分:14)

听起来您想要从已知参数中实例化“冻结”分布。在您的示例中,您可以执行以下操作:

from scipy.stats import lognorm
stddev = 0.859455801705594
mean = 0.418749176686875
dist=lognorm([stddev],loc=mean)

将为您提供一个lognorm分布对象,其中包含您指定的均值和标准差。然后你可以像这样得到pdf或cdf:

import numpy as np
import pylab as pl
x=np.linspace(0,6,200)
pl.plot(x,dist.pdf(x))
pl.plot(x,dist.cdf(x))

lognorm cdf and pdf

这是你的想法吗?

答案 2 :(得分:9)

from math import exp
from scipy import stats

def lognorm_cdf(x, mu, sigma):
    shape  = sigma
    loc    = 0
    scale  = exp(mu)
    return stats.lognorm.cdf(x, shape, loc, scale)

x      = 25
mu     = 2.0785
sigma  = 1.744
p      = lognorm_cdf(x, mu, sigma)  #yields the expected 0.74341

与Excel和R类似,上面的 lognorm_cdf 函数使用 mu sigma 参数化CDF以获取对数正态分布。

虽然SciPy使用 shape loc scale 参数来表征其概率分布,但对于对数正态分布,我发现它稍微容易一些在变量级别而不是在分布级别考虑这些参数。这就是我的意思......

对数正态变量 X 与正常变量 Z 相关,如下所示:

X = exp(mu + sigma * Z)              #Equation 1

与:

相同
X = exp(mu) * exp(Z)**sigma          #Equation 2

这可以悄悄地重写如下:

X = exp(mu) * exp(Z-Z0)**sigma       #Equation 3

其中 Z0 = 0.此等式的格式为:

f(x) = a * ( (x-x0) ** b )           #Equation 4

如果您可以在头部可视化方程,则应明确公式4中的比例,形状和位置参数为: a b x0 ,分别。这意味着在公式3中,比例,形状和位置参数为: exp(mu) sigma 和零,尊重。

如果你不能非常清楚地想象,那么让我们将等式2重写为函数:

f(Z) = exp(mu) * exp(Z)**sigma      #(same as Equation 2)

然后查看 mu sigma f(Z)的影响。下图中的 sigma 常量并且变化 mu 。您应该看到 mu 垂直缩放 f(Z)。然而,它以非线性方式这样做;将 mu 从0更改为1的效果小于将 mu 从1更改为2的效果。从公式2我们看到 exp(mu)< / em>实际上是线性比例因子。因此,SciPy的“比例”是 exp(mu)

effects_of_mu

下一个数字保持 mu 常数并且变化 sigma 。您应该看到 f(Z)的形状发生了变化。也就是说, f(Z) Z = 0时具有常数值, sigma 影响 f(Z)远离水平轴的曲线。因此,SciPy的“形状”是 sigma

effects_of_sigma

答案 3 :(得分:3)

更晚,但如果它对其他人有帮助:我发现了Excel&#39>

LOGNORM.DIST(x,Ln(mean),standard_dev,TRUE)

提供与python&#39;

相同的结果
from scipy.stats import lognorm
lognorm.cdf(x,sigma,0,mean)

同样,Excel&#39>

LOGNORM.DIST(x,Ln(mean),standard_dev,FALSE)

似乎等同于Python的

from scipy.stats import lognorm
lognorm.pdf(x,sigma,0,mean).

答案 4 :(得分:2)

@lucas' answer使用率下降。作为代码示例,您可以使用

import math
from scipy import stats

# standard deviation of normal distribution
sigma = 0.859455801705594
# mean of normal distribution
mu = 0.418749176686875
# hopefully, total is the value where you need the cdf
total = 37

frozen_lognorm = stats.lognorm(s=sigma, scale=math.exp(mu))
frozen_lognorm.cdf(total) # use whatever function and value you need here

答案 5 :(得分:0)

如果您阅读此内容并且只想要一个行为与R中的lnorm类似的行为。那么,请免受暴力愤怒并使用numpy&#39; numpy.random.lognormal