web-dev-qa-db-ja.com

MuとSigmaを使用してPythonで対数正規分布を取得するにはどうすればよいですか?

Scipy を使用して lognormal 分布の結果を取得しようとしています。私はすでに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)

UPDATE:

それで、少しの作業と少しの調査の後、私はもう少し進んだ。しかし、私はまだ間違った答えを得ています。新しいコードは以下のとおりです。 RとExcelによると、結果は。7434になるはずですが、それは明らかに何が起こっているのかではありません。私が見落としている論理上の欠陥はありますか?

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

UPDATE 2:正しい0.7434結果が得られる実用的なlognorm実装。

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
22
Eric Lubow

既知のパラメータから「フリーズ」分布をインスタンス化したいようです。あなたの例では、あなたは次のようなことをすることができます:

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

これにより、指定した平均と標準偏差をもつ対数ノルム分布オブジェクトが得られます。その後、次のように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

これはあなたが考えていたものですか?

15
talonmies

私はこれが少し遅い(ほぼ1年です!)ことを知っていますが、scipy.statsのlognorm関数についていくつかの調査を行っています。多くの人が入力パラメータについて混乱しているようですので、私はこれらの人々を助けたいと思います。上記の例はほぼ正しいですが、平均を場所( "loc")パラメーターに設定するのはおかしいです-これは、値が平均より大きくなるまでcdfまたはpdfが「離陸」しないことを示します。また、平均および標準偏差の引数は、それぞれexp(Ln(mean))およびLn(StdDev)の形式である必要があります。

簡単に言えば、引数は(x、shape、loc、scale)で、以下のパラメーター定義があります。

loc-同等のものはありません。これはデータから差し引かれ、0はデータの範囲の最小値になります。

scale-expμ、ここでμは変量の対数の平均です。 (フィッティングするときは、通常、データのログのサンプル平均を使用します。)

形状-変量の対数の標準偏差。

私はこの機能を持つほとんどの人々と同じ欲求不満を経験したので、私の解決策を共有しています。リソースの概要がないと説明が明確にならないので、注意してください。

詳細については、次のソースが参考になりました。

そして、これは、このページに投稿された@ 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
30
modulitos
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 を使用して対数正規分布のCDFをパラメーター化しますおよび sigma

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)は、実際には線形スケーリング係数です。したがって、SciPyの「スケール」は exp(mu)です。

effects_of_mu

次の図は mu 定数を保持し、 sigma を変化させます。 f(Z)の形状が変化することがわかります。つまり、 f(Z)は、 [〜#〜] z [〜#〜] = 0および sigma は、 f(Z)が水平軸から離れる速度に影響します。したがって、SciPyの「形状」は sigma です。

effects_of_sigma

9
ToddP

さらに遅くなりますが、それが他の人に役立つ場合は、Excelの

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

pythonのと同じ結果を提供します

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

同様に、Excelの

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

pythonのと同等のようです

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

@ lucas 'の回答 は使用量が少なくなっています。コード例として、あなたは使うことができます

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
2
serv-inc

これを読んで、Rのlnormと同様の動作の関数が必要な場合は、暴力的な怒りから解放され、numpyのnumpy.random.lognormalを使用してください。

0