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

Eri*_*bow 22 python statistics scipy

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

这是我正在使用的代码示例.谢谢.

from scipy.stats import lognorm
stddev = 0.859455801705594
mean = 0.418749176686875
total = 37
dist = lognorm.cdf(total,mean,stddev)
Run Code Online (Sandbox Code Playgroud)

更新:

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

dist = lognorm([1.744],loc=2.0785)
dist.cdf(25)  # yields=0.96374596, expected=0.7434
Run Code Online (Sandbox Code Playgroud)

更新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
Run Code Online (Sandbox Code Playgroud)

mod*_*tos 29

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

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

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

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

shape - 变量日志的标准偏差.

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

有关更多信息,我发现这些来源很有用:

这里有一个例子,取自@ serv-inc的答案,在这个页面上发布:

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
Run Code Online (Sandbox Code Playgroud)

  • 如果我猜对了:在数学符号中,如果 X 是 N(mu,sigma) 那么 Y=exp(X) 是 LogN(mu, sigma)。要在 scipy 中获得 X,我将使用 norm(mu,sigma) 但要获得 YI 将使用 lognorm(sigma, 0, exp(mu))。这很尴尬... (2认同)
  • 顺便说一句:我发现你的帖子有帮助,但不是 scipy 帮助。对于每一个分布,你真的必须尝试参数的含义可能是什么(例如对于均匀分布 U(a,b),其中 [a,b] 是你需要的区间 uniform(loc=a, scale =ba),这里 loc 不是平均值,也不是缩放 stddev...) (2认同)
  • @ElmarZander:您可以使用`lognorm(s = sigma,scale = math.exp(mu)`.请参阅http://stackoverflow.com/a/36714419/1587329 (2认同)

tal*_*ies 15

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

from scipy.stats import lognorm
stddev = 0.859455801705594
mean = 0.418749176686875
dist=lognorm([stddev],loc=mean)
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个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))
Run Code Online (Sandbox Code Playgroud)

lognorm cdf和pdf

这是你的想法吗?

  • 那么根据卢卡斯下面的回答,这是错误的,对吗?平均值不应该位于分布的最左侧,而应该位于峰值的右侧,对吧? (2认同)

Tod*_*ddP 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
Run Code Online (Sandbox Code Playgroud)

与Excel和R类似,上面的lognorm_cdf函数使用musigma参数化CDF以获得对数正态分布.

虽然SciPy使用shape,locscale参数来表征其概率分布,但对于对数正态分布,我发现在变量级别而不是在分布级别上更容易想到这些参数.这就是我的意思......

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

X = exp(mu + sigma * Z)              #Equation 1
Run Code Online (Sandbox Code Playgroud)

这与:

X = exp(mu) * exp(Z)**sigma          #Equation 2
Run Code Online (Sandbox Code Playgroud)

这可以偷偷地重写如下:

X = exp(mu) * exp(Z-Z0)**sigma       #Equation 3
Run Code Online (Sandbox Code Playgroud)

其中Z0 = 0.这个等式的形式如下:

f(x) = a * ( (x-x0) ** b )           #Equation 4
Run Code Online (Sandbox Code Playgroud)

如果您可以在头部可视化方程,则应该清楚公式4中的比例,形状和位置参数分别为:a,bx0.这意味着在等式3中,尺度,形状和位置参数分别为:exp(mu),sigma和零.

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

f(Z) = exp(mu) * exp(Z)**sigma      #(same as Equation 2)
Run Code Online (Sandbox Code Playgroud)

然后看看musigmaf(Z)的影响.下图保持西格玛常数并且变化μ.您应该看到mu垂直缩放f(Z).然而,它以非线性方式这样做; 将μ从0变为1的效果小于将mu从1变为2 的效果.从等式2可以看出,exp(mu)实际上是线性比例因子.因此,SciPy的"比例"是exp(mu).

effects_of_mu

下一个数字保持mu不变并且变化sigma.您应该看到f(Z)的形状发生变化.也就是说,当Z = 0 时,f(Z)具有恒定值,并且sigma影响f(Z)远离水平轴弯曲的速度.因此,SciPy的"形状"就是西格玛.

effects_of_sigma