Up

2×2分割表の検定

Fishers Exact Test

 

2×2分割表の検定において、カイ2乗分布による近似が良くない例を示すシミュレーションがこのウェブサイトに公開されている。

 

本ウェブサイトでは、カイ2乗分布による近似ではなく、フィッシャーの直接(確率)検定を行うのためのスクリプトを書いてみた(リスト)。

Fishers 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 Fishers 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でデータ分析.丸善出版

 

 

 

Home