最近、とある二つのサンプルの分散が異なることを確認する機会があり、F検定を行う必要がありました。
いつもみたいにSciPyですぐにできるだろうと考えていたのですが、
Statistical functions をみる限りでは、SciPyにF検定は実装されていなさそうでした。
その代わり、バートレット検定とルビーン検定が実装されているのですが。
この二つの検定については別途勉強するとして、とりあえずF検定を行いたかったので自分で実装しました。
幸い、F分布自体はSciPyにあるので簡単です。
t検定のメソッドを参考にし、サンプルを二つ渡したらF統計量とp値を返してくれる関数ように実装しました。
※F検定自体の説明は今回は省略します。
興味のあるかたには、東大出版会の統計学入門(いわゆる赤本)の244ページ、12.2.4 母分散の比の検定 あたりが参考になります。
from scipy.stats import f
import numpy as np
def ftest(a, b):
# 統計量Fの計算
v1 = np.var(a, ddof=1)
v2 = np.var(b, ddof=1)
n1 = len(a)
n2 = len(b)
f_value = v1/v2
# 帰無仮説が正しい場合にFが従う確率分を生成
f_frozen = f.freeze(dfn=n1-1, dfd=n2-1)
# 右側
p1 = f_frozen.sf(f_value)
# 左側
p2 = f_frozen.cdf(f_value)
# 小さい方の2倍がp値
p_value = min(p1, p2) * 2
# 統計量Fとp値を返す
return f_value, p_value
きちんと実装できているかどうか確認するため、統計学入門の練習問題を一つ解いておきます。
252ページの練習問題、 12.2 の iii) が分散の検定なのでやってみます。
次のコードのdata_1とdata_2の分散が等しいというのが帰無仮説で、等しくないというのが対立仮説です。
# 問題文のデータを入力
data_1 = np.array([15.4, 18.3, 16.5, 17.4, 18.9, 17.2, 15.0, 15.7, 17.9, 16.5])
data_2 = np.array([14.2, 15.9, 16.0, 14.0, 17.0, 13.8, 15.2, 14.5, 15.0, 14.4])
# F統計量とp値を計算
f_value, p_value = ftest(data_1, data_2)
print(f"F統計量: {f_value:1.3f}")
# F統計量: 1.564
print(f"p値: {p_value:1.3f}")
# p値: 0.516
F統計量は正解と一致しましたし、帰無仮説が棄却できないのも確認できました。