正規分布かどうかを見極める3つのステップ(Pythonでの検定実践あり)
学校の授業や資格のテストでは、「正規分布をしている」ことを前提に、検定や推定が行われることが多いですよね。
しかし、実際に自分でデータをとって分析する時は、当然ですが誰もそのデータ郡が「正規分布をしている」とは保証してくれないわけです。
そのため、データ解析を始めるその前に「正規性の検定(正規分布しているかどうかの確認)」をしなければなりません。
今回は、正規分布かどうかを見極めるための検定と手法を、Pythonを用いてやっていきたいと思います。
注)* 標準偏差・ヒストグラムなどを理解していない初学者の方はまずこちらから参照することをおすすめします。 www.ie-kau.net
目次:正規分布かどうか見極める手順
- まずはサンプルデータの作成から
- ヒストグラムとQQプロットで視覚的に確認する
- 法則を使って正規性を検定する
1. まずはサンプルデータの作成から
データがあったほうがわかりやすいはず!とのことで、まずはサンプルデータの作成から入りたいと思います。
標準正規分布に従う乱数と、比較のための適当な乱数をそれぞれ1000づつ作成します。
from numpy.random import * import numpy as np import scipy.stats as stats import pandas normal = randn(1000) # 標準正規分布に従う乱数を1000個生成 comparison = rand(1000) #比較のため乱数を1000個生成
これでnormalのほうが正規分布かに従うデータ、comparisonにはランダムなデータが入っています。
2. ヒストグラムとQQプロットで視覚的に確認する
正規生の検定にかぎらず、データのキモをつかむのに、グラフを使って視覚化することはすごく大事です。
グラフを作れば、「こんな感じか!」というのがわかるので、当たりをつけて分析ができるようになるんですよね。
それでは normal と comparison のグラフを出力して表示してみましょう。
ヒストグラムとQQプロットで視覚的に確認する
ヒストグラム
normal
plt.hist(normal, bins=100)
comparison
plt.hist(comparison, bins=100)
normalのほうが、真ん中によっていて正規分布っぽいグラフになっています。
ここではなんとなく正規分布なんだろうな、くらいで十分です。
QQプロット
QQプロットとは、X軸上に観測した累積パーセント、Y軸上に期待累積パーセントを持つグラフのことです。
ヒストグラムよりなじみは薄いと思うので、わからなければ 一直線上になっていれば正規分布であるくらいに覚えておけばOKです。
normal
stats.probplot(normal, dist="norm", plot=pylab)
comparison
stats.probplot(normal, dist="norm", plot=pylab)
やはりnormalのほうは一直線上に並んでますね。赤の補助線とほぼ同期しているため、もうここで正規分布と判断してもいいくらいかな〜、なんて思ったりもしますが、せっかくなので最後までやりましょう。
3. 法則を使って正規性を検定する (シャピロウィルク検定)
いわゆるひとつの、関数というか先人の知恵を借りる方法です。
シャピロウィルク検定だけやって済ます、というチートもあるのですが。。
やはりグラフを描いて感覚を掴んでからのほうが、データに対する理解度から、その後の分析に役立ちます。手順はしっかりと踏みましょう。
normal
stats.shapiro(normal)
(0.9980230331420898, 0.29242318868637085)
出力結果は(W, p値)となります。
p値が0.05以下の場合は棄却されるので、normal は正規分布と判断してよし、となります。
comparison
stats.shapiro(comparison)
(0.955951988697052, 9.170879321226003e-17)
p値が限りなく低いので、こちらは棄却できず、正規分布とはいえないですね。
以上でnormalは正規分布に従い、comparisonは従わないとわかりました。やったー
おまけ. 歪度と尖度が正規分布に近い値か確認する
歪度とは、グラフがどれくらい平均の回りに対称に分布していないかを示す数値で、0に近ければ近いほど正規分布に近い数値になります。
尖度とは、グラフがどれくらい尖っているかを表す数値です。こちらは-3して0になる値が正規分布に近い数値になります。
調べた限りだと歪度と尖度のPythonでの出し方があんまり載ってなかったので、メモがてらに置いときます。
pd.Series(normal).skew() #歪度 pd.Series(normal).kurtosis() #尖度
まとめ
RやPythonのおかげでライブラリが充実し、詳しく統計知識がなくてもかんたんに検定や推定が出来るようになっていますが、分布によって当てはめられる公式は違うので、ココらへんはしっかり理解しておきたいところです。
∠(`・ω・´)オラッオラッ