技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く興味があります。

pythonで一元配置分散分析(one way ANOVA)

一元配置分散分析とは

「3つ以上の群があった時に、果たしてそれらの群の平均は等しいと言えるかどうか。」
という検定。
集団の分布が正規性を持つことが前提となっている。
※すべての組み合わせペアでt検定を適用するのは間違いなので注意f:id:swdrsker:20170613190057p:plain*1

基本的な発想は、
「集団間の分散と集団内のばらつきを比べて、集団間のばらつきの方が大きいと見なせれば集団間に違いがある。」
と考えるという仕組みになっている。

方法

帰無仮説と対立仮設は以下のようになる。

  • 帰無仮説:集団間の平均に違いはない
  • 対立仮設:少なくとも1つの集団の平均が他の集団と異なる

上で説明したような
「集団内の分散から見た集団間のばらつきの大きさ」
F値と呼び、これがF分布に従うことを利用して検定を行う。

F値が有意に大きい見なされると帰無仮説が棄却され、「集団の平均がすべて同じとは言えない」と言える。

Pythonのコード

例によってscipyが使える。

scipy.stats.f_oneway(*args)

argsには集団のデータが入る。
p値はpvalueで取り出す。

テストコード

平均が同じ集団

まず、帰無仮説が採択される場合を見てみる。
例えば、下の3つを比較してみよう。

  1. 平均10 分散5 標本数90
  2. 平均10 分散10 標本数120
  3. 平均10 分散20 標本数100
import matplotlib.pyplot as plt
import numpy as np

a1 = np.random.normal(10,5,size=90)
a2 = np.random.normal(10,10,size=120)
a3 = np.random.normal(10,20,size=100)
bins = np.arange(-30,50,5)
plt.hist(a1, bins=bins, alpha=0.3)
plt.hist(a2, bins=bins, alpha=0.3)
plt.hist(a3, bins=bins, alpha=0.3)
result = scipy.stats.f_oneway(a1,a2,a3)
print(result.pvalue)
plt.show()

0.352570030224
f:id:swdrsker:20170613184005p:plain

この場合、
有意水準5%とすると
0.353>0.05
なので、集団間の平均値に差異はないことが分かった。

平均が異なる集団

次に、帰無仮説が棄却される場合を見てみる。
上のデータを少し変えて

  1. 平均10 分散5 標本数90
  2. 平均15 分散10 標本数120
  3. 平均10 分散20 標本数100

としてみる

import matplotlib.pyplot as plt
import numpy as np

a1 = np.random.normal(10,5,size=90)
a2 = np.random.normal(15,10,size=120)
a3 = np.random.normal(10,20,size=100)
bins = np.arange(-30,50,5)
plt.hist(a1, bins=bins, alpha=0.3)
plt.hist(a2, bins=bins, alpha=0.3)
plt.hist(a3, bins=bins, alpha=0.3)
result = scipy.stats.f_oneway(a1,a2,a3)
print(result.pvalue)
plt.show()

0.00362625959975
f:id:swdrsker:20170613183903p:plain

この場合は、
有意水準5%とすると
0.004<0.05より
帰無仮説は棄却される。
「少なくとも1つの集団の平均値が異なる」ことがわかる。


参考サイト
立教大学の授業スライド:わかりやすくまとまってある。
scipy.stats.f_oneway — SciPy v0.19.0 Reference Guide

関連記事: