SciPy.stats#
import japanize_matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 警告メッセージを非表示
import warnings
warnings.filterwarnings("ignore")
SciPy
(サイパイ)は,NumPyの大幅な拡張版と理解して良い。SciPy
を読み込むとNumPyの関数などを利用できるようになる。しかしSciPy
は大きなパッケージであり,全てを読み込む必要もない。従って,NumPy
を読み込んで,SciPy
のサブパッケージや関数を読み込むということで十分であろう。ここではSciPy
のstats
というサブパッケージについて説明する。
正規分布(Normal Distribution)#
正規分布のモジュール名はnorm
であり,以下が主な関数である。
確率密度関数:
norm.pdf(x, loc=0, scale=1)
pdf
はProbability Density Functionの頭文字loc
= 平均scale
= 標準偏差x
= \(-\infty\)から\(\infty\)の間の値返り値:
x
の値が発生する確率(%)loc
とscale
を省略すると標準正規分布の確率密度関数となる。
累積分布関数:
norm.cdf(x, loc=0, scale=1)
cdf
はCumulative Distribution Functionの頭文字loc
= 平均scale
= 標準偏差x
= \(-\infty\)から\(\infty\)の間の値返り値:
x
以下の値が発生する確率(%)loc
とscale
を省略すると標準正規分布の累積分布関数となる。
パーセント・ポイント関数:
norm.ppf(a, loc=0, scale=1)
ppf
はPercent Point Functionの頭文字loc
= 平均scale
= 標準偏差a
= 0 ~ 1の間の値返り値:累積分布関数の値が
a
である場合のx
の値(累積分布関数の逆関数)loc
とscale
を省略すると標準正規分布のパーセント・ポイント関数となる。
ランダム変数生成関数:
norm.rvs(loc=0, scale=1, size=1)
rvs
はRandom VariableSの大文字の部分loc
= 平均scale
= 標準偏差size
= 生成されるランダム変数の数返り値:正規分布に従って発生したランダム変数
loc
とscale
を省略すると標準正規分布のランダム変数生成関数となる。
scipy.stats
のnorm
を読み込む。
from scipy.stats import norm
確率密度関数
norm.pdf(0)
0.3989422804014327
0
が発生する確率は約39.9%
とわかる。norm.pdf(x)
のグラフを描くためには,\(\infty\)から\(\infty\)のx
の返り値が必要になるが,ここでは-4
から4
の区間で100個のx
の値で近似する。
x = np.linspace(-4, 4, 100)
このx
を直接norm.pdf()
に代入すると,全てのx
の値に対しての返り値を得ることができる。それをy_pdf
に割り当てる。
y_pdf = norm.pdf(x) # 標準正規分布
plt.plot(x,y_pdf)
plt.xlabel('x')
plt.ylabel('p')
plt.title('Standard Normal Distribution')
pass
累積分布関数
y_cdf = norm.cdf(x) # 標準正規分布
plt.plot(x, y_cdf)
plt.xlabel('x')
plt.ylabel('P')
plt.title('Cumulative Distribution Function')
pass
この関数を使うことにより,x
の値が\(X\)の時,それ以下の値が発生する確率は何%かを計算できる。例えば,x
が\(0\)以下の値を取る確率は
norm.cdf(0)
0.5
確率密度関数が平均\(0\)(loc=0
)を中心に左右対称のため確率は50%となる。では,x
が\(-4\)以下の場合は?
norm.cdf(-4)
3.167124183311986e-05
返り値の最後のe-05
は\(\times 10^-5\)という意味。では,x
が4以上の確率は?
1-norm.cdf(4)
3.167124183311998e-05
パーセント・ポイント関数
p = np.linspace(0,1,100)
y_ppf = norm.ppf(p) # 標準正規分布
plt.plot(p,y_ppf)
plt.xlabel('P')
plt.ylabel('x')
plt.title('Percent Point Function')
pass
パーセント・ポイント関数を使い,累積分布関数の値がP
である場合のx
の値を計算できる。P=0.5
の場合のx
は?
norm.ppf(0.5)
0.0
P=0.025
の場合のx
は?
norm.ppf(0.025)
-1.9599639845400545
P=0.975
の場合のx
は?
norm.ppf(0.975)
1.959963984540054
ランダム変数生成関数
10000個のランダム変数を生成しよう。
y_rvs = norm.rvs(size=10_000) # 標準正規分布
plt.hist(y_rvs, bins=30) # bins=表示する棒の数(デフォルトは10)
pass
y_rvs
は標準正規分布から生成されたが,y_rvs
がどの分布関数から生成されたか不明だったとしよう。更に,y_rvs
から元の確率密度関数を推定したいとしよう。その際に使う手法をカーネル密度推定と呼ぶ。SciPy
にはそのための関数gaussian_kde
が用意されている。gaussian
(ガウシアン)とは天才数学者ガウスの名前からきており「ガウス的な」と理解すれば良い。kde
はKernel Density Estimate(カーネル密度推定)の頭文字をとっている。
from scipy.stats import gaussian_kde # サブパッケージを読み込む
kde = gaussian_kde(y_rvs) # y_rvsから確率密度関数を推定
plt.plot(x, kde(x)) # 横軸のxに対してプロット
pass
推定なので標準正規分布の確率密度関数と全く同じにはならないが,非常に近い。上の図と重ねると。
plt.hist(y_rvs, bins=30, density=True)
plt.plot(x, kde(x))
pass
plt.hist()
にあるdensity=True
は縦軸を%表示にする引数である。これによりplt.hist
のヒストグラムとplt.plot()
のカーネル密度関数が同じスケールで表示されることになる。
その他の分布関数#
\(t\)分布#
\(t\)分布のモジュール名はt
。
t.pdf(x, df)
t.cdf(x, df)
t.ppf(a, df)
t.rvs(df, size=1)
df
:自由度(degree of freedom)
scipy.stats
のt
を読み込み確率密度関数の図を表示する。
from scipy.stats import t
x = np.linspace(-4,4,100)
y = t.pdf(x, df=1)
plt.plot(x,y)
pass
df=1
の場合にx
の値が-3
以下の確率は何か?
t.cdf(-3, df=1)
0.10241638234956672
df=1
の場合にx
の値が3
以上の確率は何か?
1-t.cdf(3, df=1)
0.10241638234956674
\(t\)分布と標準正規分布は正規分布は非常に類似性が高い。自由度が30
になれば,両分布の誤差は非常に小さくなることが知られている。確認するために,プロットしてみよう。
x = np.linspace(-4, 4, 100)
plt.plot(x, t.pdf(x, 30), label=r'$t$ 分布')
plt.plot(x, norm.pdf(x), label='標準正規分布')
plt.legend()
pass
\(\chi^2\)分布#
\(\chi^2\)分布のモジュール名はchi2
。
chi2.pdf(x, df)
chi2.cdf(x, df)
chi2.ppf(a, df)
chi2.rvs(df, size=1)
df
:自由度(degree of freedom)
scipy.stats
のchi2
を読み込み確率密度関数の図を表示する。
from scipy.stats import chi2
x = np.linspace(0,12,100)
y = chi2.pdf(x, df=3)
plt.plot(x,y)
pass
df=3
の場合にx
の値が1
以下の確率は何か?
chi2.cdf(1, df=3)
0.19874804309879915
df=3
の場合にx
の値が10
以上の確率は何か?
1-chi2.cdf(10, df=3)
0.0185661354630432
\(F\)分布#
\(F\)分布のモジュール名はf
。
f.pdf(x, dfn, dfd)
f.cdf(x, dfn, dfd)
f.ppf(a, dfn, dfd)
f.rvs(dfn, dfd, size=1)
dfn
:分子の自由度(numerator degree of freedom)dfd
:分母自由度(denominator degree of freedom)
scipy.stats
のf
を読み込み確率密度関数の図を表示する。
from scipy.stats import f
x = np.linspace(0.001,5,1000)
y = f.pdf(x, dfn=5, dfd=1)
plt.plot(x,y)
pass
dfn=5
, dfd=1
の場合にx
の値が0.1
以下の確率は何か?
f.cdf(0.1, dfn=5, dfd=1)
0.02503101581845294
dfn=5
, dfd=1
の場合にx
の値が5
以上の確率は何か?
1-f.cdf(5, dfn=5, dfd=1)
0.32657156446244606
一様分布 (Uniform Distribution)#
一様分布のモジュール名はuniform
。
uniform.pdf(x, loc=0, scale=1)
uniform.cdf(x, loc=0, scale=1)
uniform.ppf(a, loc=0, scale=1)
uniform.rvs(loc=0, scale=1, size=1)
loc
:x
の最小値scale
:x
の幅x
の最大値:loc+scale
m
だけ「右」に平行移動させる場合は
loc=m # scaleは省略
scipy.stats
のuniform
を読み込み確率密度関数の図を表示する。
from scipy.stats import uniform
x = np.linspace(0,12,100)
y = uniform.pdf(x, loc=1, scale=9)
plt.plot(x,y)
pass
ロジスティク分布(Logistic Distribution)#
ロジスティック分布のモジュール名はlogistic
。
logistic.pdf(x, loc=0, scale=1)
logistic.cdf(x, loc=0, scale=1)
logistic.ppf(a, loc=0, scale=1)
logistic.rvs(loc=0, scale=1, size=1)
loc
:平均値scale
:分散に影響する値
logistic.pdf(x,loc,scale) = logistic.pdf(z), z=(x-loc)/scale
scipy.stats
のlogistic
を読み込み確率密度関数の図を表示する。
from scipy.stats import logistic
x = np.linspace(-5,5,100)
y = logistic.pdf(x)
plt.plot(x,y)
pass