我一直在尝试使用lognormal获取Scipy发布的结果。我已经拥有Mu和Sigma,所以我不需要做任何其他准备工作。如果我需要更具体(并且我试图利用我对统计数据的有限知识),我会说我正在寻找累积函数(在Scipy下的cdf)。问题是我无法弄清楚如何只用0-1的平均值和标准差来做到这一点(即返回的答案应该是0-1的答案)。我也不确定 dist 采用哪种方法,我应该用它来得到答案。我已经尝试阅读文档并查看SO,但相关问题(如this和this)似乎没有提供我正在寻找的答案。
以下是我正在使用的代码示例。感谢。
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
答案 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))
这是你的想法吗?
答案 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)。
下一个数字保持 mu 常数并且变化 sigma 。您应该看到 f(Z)的形状发生了变化。也就是说, f(Z)在 Z = 0时具有常数值, sigma 影响 f(Z)< em>远离水平轴的曲线。因此,SciPy的“形状”是 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
。