2×2分割表の検定
Fisher’s Exact Test
2×2分割表の検定において、カイ2乗分布による近似が良くない例を示すシミュレーションがこのウェブサイトに公開されている。
本ウェブサイトでは、カイ2乗分布による近似ではなく、フィッシャーの直接(確率)検定を行うのためのスクリプトを書いてみた(リスト1)。
Fisher’s exact testは、Conover (1999),pp.188-189に従ってスクリプトを作成した。
いま、分割表が表1のように与えられているとする。
表1 2×2分割表 |
|
|
|
|
列1 |
列2 |
和 |
行1 |
|
|
|
行2 |
|
|
|
和 |
|
N-c |
|
表1の分割表において、左上のセルの値がである確率が超幾何分布で与えられる。
ここで、の値が小さいとき、表1の行2列2のセルの値が負になることがあるが、超幾何分布を与える関数は、このとき値0を返すので、の変域は、上式で考えてプログラミングができる。
下記コードで超幾何分布の累積確率密度を配列cumPsに設定している。
Ps = []
# List of probability
masses
for x in range(np.min([r,c])+1):
Ps.append(ss.hypergeom.pmf(x,
N, r, c))
cumPs = np.cumsum(Ps) # Cumulative probabilities
累積確率密度を表す配列cumPsにより、以下のコードで片側検定のp値、および両側検定のp値を算出している。
Lower_tailed = cumPs[t_obs]
Upper_tailed = 1.0 - cumPs[t_obs-1] if
t_obs > 0 else 1.0
Two_tailed = 2 * np.min([Lower_tailed,
Upper_tailed])
リスト1のスクリプトを実行すると、入力データファイル名の設定が求められる。
Input Data
File(*.csv) =
入力データファイルは、CSV形式のファイルとして用意する。
図1のファイルは、Conover (1999)のEXAMPLE 3 (p.190)で用いられているデータを表計算ソフトのシートに設定したものである。
図1 入力データファイル例(*.csv)
データは、1行目および1列目にカテゴリ名を設定して、対応する行および列カテゴリの組み合わせに対応するセルに度数を設定する。検定は、セルの並びの左上の位置にある値、図1の場合は1,に注目して行われる(式(1))。
なお、カテゴリ名は、日本語を用いず、英数字の文字列で設定する。日本語を用いると、pd.read_csvによる読み込み時にエラーとなる。
シートに設定したデータをファイル拡張子「.csv」を選んで保存すると、CSV形式のファイルとして保存される。
入力ファイル名の例として図1のファイル名Example3.csvを設定する。
Input Data
File(*.csv) = Example3.csv
Enterキーを押すと、ファイルが読み込まれて、計算結果が以下のように端末に出力される。
Lower_tailed = 0.04095904095904096
Upper_tailed = 0.999000999000999
Two_tailed = 0.08191808191808192
図1の表の左上の値1が有意に小さい値であるかという片側検定のときは、下側(左側)のp値が0.041であるので有意水準5%で有意差ありである。
図1の表の左上の値1が大き過ぎる、あるいは小さ過ぎる値であるかという両側検定のときは、p値は8.2%であり、有意水準5%で大き過ぎるあるいは小さ過ぎるとは言えない。
リスト1 Fisher’s exact test(圧縮ファイルfisherexactfiles.zipにまとめた)
import pandas as pd
import numpy as np
import scipy.stats as ss
fin_nm = input('Input Data File(*.csv)
= ')
data = pd.read_csv(fin_nm)
data = data.values[:,1:]
print(data)
#
# Conover(1999),
pp.188-189.
#
r = np.sum(data, axis=1)[0]
c = np.sum(data, axis=0)[0]
N = np.sum(data)
t_obs = data[0,0]
Ps = []
# List of probability
masses
for x in range(np.min([r,c])+1):
Ps.append(ss.hypergeom.pmf(x, N, r, c))
cumPs = np.cumsum(Ps) # Cumulative probabilities
Lower_tailed = cumPs[t_obs]
Upper_tailed = 1.0 - cumPs[t_obs-1] if
t_obs > 0 else 1.0
Two_tailed = 2 * np.min([Lower_tailed,
Upper_tailed])
print('Lower_tailed =', Lower_tailed)
print('Upper_tailed =', Upper_tailed)
print('Two_tailed =', Two_tailed)
Conover, W. J. (1999) Practical nonparametric statistics, third edition. John Wiley & Sons, Inc.
岡本安晴(2019) いまさら聞けないPythonでデータ分析.丸善出版