技術メモ

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

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

一元配置分散分析とは

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

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

方法

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

  • 帰無仮説:集団間の平均に違いはない
  • 対立仮設:少なくとも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.352>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

関連記事:

一発でlocalhostのwebサーバーを立てる便利エイリアス

Flaskで開発していたり、http通信が必要となるjsのライブラリを使っているとlocalhostのwebサーバーを立てたくなることがある。
そこで苦労の末辿り着いた便利エイリアスを紹介したい。
それがこれ

alias httpserver="python -m SimpleHTTPServer& start chrome http://localhost:8000"

pythonの環境があることが前提となっているが、linuxだと標準装備だし他環境でも環境導入が問題になることはないだろう。
ロームなんて使うかボケ!って人はfirefoxなり適宜ブラウザを変えればいい。

追記:
python3系だとうまくいかないよう。
3系の場合は前半の部分を

python -m http.server

とする
Python2系でもPython3系でも簡易Web鯖をワンライナーで立てる - tututenの備忘録


お手軽なWebサーバーの立て方 - Qiita

リスト内を検索して該当するインデックスを全て返す (python)

a = [1,2,3,2,3,4,5,4,3,2,1]

こんなデータがあった時、3がある場所を取ってきたいとする。

a.index(3)
# 2

とすると最初のインデックスだけが返ってくる。
希望は全てを取ってくることなので、これではダメ。
じゃあどうするか。

index = []
for i,j in enumerate(a):
    if j==3:
        index.append(i)
# index:[2,4,8]

numpyを使うともっときれいに書ける。そのうえ、巨大なリストだとより高速。

import numpy as np
a = np.array(a)
np.where(a==3)
# array([2,4,8], dtype=int64)

関連記事