PythonとRで独立性の検定（カイ2乗検定・フィッシャーの直接確率検定）

# 概要

「独立性の検定」に関するメモ、実施のためのPythonコード、Rコードです。
「カイ2乗検定」と「フィッシャーの直接確率検定」の内容を含みます。

### 関連エントリ
- [Pythonでt検定](https://qiita.com/code0327/items/a96dd2fbd8a491d2eeaa) 
- [F#でt検定](https://qiita.com/code0327/items/960c20ba51f9cf5430e7)
- [F#で独立性の検定](https://qiita.com/code0327/items/ddb1e8e50ae2343d99c2)


# 設定

　問題例として、次のような設定（状況）を考えていきたいと思います。

>ある学校では、学期末に自由記述欄を含んだ授業評価アンケートを実施している。
>このアンケートは、担当教員が「紙形式」か「ウェブ形式」を選んで実施している。今後、アンケートを有効活用していくために、実施形式の違いが、自由記述欄（任意）への記入の有無に対して影響してくるのか？を知りたい。

　これを検討するための資料として、現在、手元には次のようなデータ（標本）が得られているとします。表内の数値は**観測度数**になります。


||自由記述欄に記入**あり**|自由記述欄に記入**なし**|
|:--:|:-----:|:-----:|
|**紙形式**|140|150|
|**ウェブ形式**|160|180|

# カイ2乗検定（独立性の検定）

「実施形式が（自由記述欄に対するコメントの）記入の有無に影響するのか？」、つまり「『実施形式』と『記入の有無』には関連性があるのか、それとも**それらは独立していて関連性がない**のか？」を判断していきます。この独立性を評価するために、**カイ2乗検定**（$\chi^2$ 検定）を利用することができます（フィッシャーの直接確率検定は後ほど）。

　カイ2乗検定では**「変数間に関連性がない」を帰無仮説**とします（ここでは「実施形式」と「記入有無」が変数となります）。そして、その「変数間に関連性がない」という仮定が正しいとして、仮に何度も標本を無作為抽出したときに「**今回のような標本や、さらに極端な標本が得られるケース**」がどの程度の確率で発生するのか？という値（$p$ 値）を求め、それと**事前設定した有意水準** $\alpha$ を比較して判断します。

　なお、「さらに極端な標本」とは「（手元にある標本よりも）変数間に関連性がありそうなことを匂わせる標本」のことです、例えば「紙形式では記入割合が $5\%$、ウェブ形式では記入割合が $85\%$」のような標本のことです。

## Pythonで実行

　カイ2乗検定を行なうPythonコードを以下に示します。データはpandasのDataFrameに格納されていることを想定しています。

```Python:カイ2乗検定（Python版）
import pandas as pd
import scipy.stats as st
df = pd.DataFrame([[140,150],   # 紙形式　　　で　記入ありの度数, 記入なしの度数
                   [160,180]])  # ウェブ形式　で　記入ありの度数, 記入なしの度数
x2, p, dof, e = st.chi2_contingency(df,correction=False)
print(f'p値 　　　= {p :.3f}')
print(f'カイ2乗値 = {x2:.2f}')
print(f'自由度　  = {dof}')
```

```:実行結果
p値 　　　= 0.760
カイ2乗値 = 0.09
自由度　  = 1
```

　あらかじめ決めておいた有意水準 $\alpha$ が $5\%$（$=0.05$）とすれば、実行結果は $p\ge0.05$ となるので**帰無仮説を採択**します。つまり、**統計学的には「実施形式」と「記入の有無」に関連性はない（それらは独立している）**と結論付けます。つまり「アンケートの自由記述欄にコメントが書かれるかどうかは、アンケートの実施形式には無関係」といえそうです。

　なお、以下のように**行と列を入れ替え**ても、同じ実行結果となります。

```Python:
df = pd.DataFrame([[140,160], 
                   [150,180]])
```

　ところで、上記では、`chi2_contingency` に引数 `correction=False` を指定しています。これは「**イェーツの補正**（イェーツの連続修正）」を適用しない、というオプションになります。カイ2乗検定の原理について解説しているページなどを見ながら試すような場合には、「イェーツの補正をしない」に設定しておくとよいです。

　なお、デフォルトでは `correction=True` になります。Wikipediaによれば「イェイツの修正の効果はデータのサンプル数が少ない時に統計学的な重要性を過大に見積もりすぎることを防ぐことである」とのことです。 `correction=True` として実行すると、次のような結果となります。

```:実行結果（イェーツ補正あり）
p値 　　　= 0.822
カイ2乗値 = 0.05
自由度　  = 1
```

## R版

　同様のことを R を使って行ないました。

```R:カイ2乗検定_イェーツの補正なし（R版）
m=matrix(c(140, 150, 160, 180), nrow=2, byrow=T)
chisq.test(m,correct=F)
```

```:実行結果

	Pearson's Chi-squared test

data:  m
X-squared = 0.092937, df = 1, p-value = 0.7605
```

　つづいて、イェーツの補正ありのバージョンです。

```R:カイ2乗検定_イェーツの補正あり（R）
m=matrix(c(140, 150, 160, 180), nrow=2, byrow=T)
chisq.test(m)
```

```:実行結果

	Pearson's Chi-squared test with Yates' continuity correction

data:  m
X-squared = 0.050549, df = 1, p-value = 0.8221
```




## どのようにp値は計算されるのか

　帰無仮説が正しく「実施形式」と「記入の有無」に**変数間に関連性がない**とき、つまり**変数は独立である**ときに期待される度数（これを**期待度数**という）と、実際の観測度数の差の2乗を、期待度数で割ったものの総和（これを**カイ2乗値**という）を求め、これとカイ2乗分布から $p$ 値を計算します。

　**期待度数**は、変数が独立であるとすれば、**次式が成立するはず**ということに基づき計算できます。

- <font color=red>**紙**</font>形式で記入<font color=red>**あり**</font>の割合＝（<font color=red>**紙**</font>形式の割合）$\times$（記入<font color=red>**あり**</font>の割合）
- <font color=red>**紙**</font>形式で記入<font color=blue>**なし**</font>の割合＝（<font color=red>**紙**</font>形式の割合）$\times$（記入<font color=blue>**なし**</font>の割合）
- <font color=blue>**ウェブ**</font>形式で記入<font color=red>**あり**</font>の割合＝（<font color=blue>**ウェブ**</font>形式の割合）$\times$（記入<font color=red>**あり**</font>の割合）
- <font color=blue>**ウェブ**</font>形式で記入<font color=blue>**なし**</font>の割合＝（<font color=blue>**ウェブ**</font>形式の割合）$\times$（記入<font color=blue>**なし**</font>の割合）

 期待度数を実際に求めてみます。まず、観測度数は次のようになっていました（合計欄を追加しました）。

||記入**あり**|記入**なし**|計|
|:--:|:-----:|:-----:|:---:|
|**紙形式**|140|150|290|
|**ウェブ形式**|160|180|340|
|**計**|300|330|630|


　ここで、「<font color=red>**紙**</font>形式の割合」は表の4列目から $290/630\risingdotseq 0.46$ 、「<font color=blue>**ウェブ**</font>形式の割合」は $340/630\risingdotseq 0.54$ のように求めることができます。また、表の4行目から「記入<font color=red>**あり**</font>の割合」は $300/630\risingdotseq 0.48$、「記入<font color=blue>**なし**</font>の割合」は $330/630\risingdotseq0.52$ となります。


　あとは、これらを使って「<font color=red>**紙**</font>形式で記入<font color=red>**あり**</font>の割合＝（<font color=red>**紙**</font>形式の割合）$\times$（記入<font color=red>**あり**</font>の割合）＝$(290/630)\times(300/630)\risingdotseq0.219$」を求めます。そして、それに $630$ をかけると、次のように期待度数が求まります。


||記入**あり**|記入**なし**|
|:--:|:-----:|:-----:|
|**紙形式**|138.1|151.9|
|**ウェブ形式**|161.9|178.1|


　この期待度数と観測度数の差の2乗を、期待度数で割ったものの総和（＝カイ2乗値）を求め、これとカイ2乗分布から $p$ 値を計算します（詳細は、別資料参照ください）。なお、期待度数は次のように `st.chi2_contingency` の戻値の4番目に格納されています。

```Python:
import pandas as pd
import scipy.stats as st
df = pd.DataFrame([[140,150], [160,180]]) 
x2, p, dof, e= st.chi2_contingency(df,correction=False)
print(f'期待度数 : \n {e}')
```

```:実行結果
期待度数 : 
 [[138.0952381 151.9047619]
 [161.9047619 178.0952381]]
```

# フィッシャーの直接確率検定

　カイ2乗検定は、一部に極端に小さい観測度数（5未満？）を含んでいる場合に適切な検定ができないことが知られています。特に問題例のように $2\times2$（2行2列）のケースでは、すべての観測度数が10以上であることが望ましいようです（参考資料[5]）。そのような場合では、カイ2乗検定ではなく**フィッシャーの直接確率検定（フィッシャーの正確確率検定）**を使用します。

　なお、十分な観測度数が得られている標本に対しても**フィッシャーの直接確率検定**は有効です。ただし、フィッシャーの直接確率検定は、観測度数の階乗計算を含むため、計算が大変になることがデメリットになります（問題例では観測度数に140がありますが、140の階乗はとても大きな数になるため計算に工夫が必要です）。Pythonのライブラリを利用するうえでは、あまり気になりませんが。

```Python:フィッシャーの正確確率検定（Python）
import pandas as pd
import scipy.stats as st
df = pd.DataFrame([[140,150], [160,180]]) 
_, p = st.fisher_exact(df)
print(f'p値 = {p :.3f}')
```

```:実行結果
p値 = 0.810
```

　有意水準 $\alpha$ が $5\%$（$=0.05$）とすれば、実行結果は $p\ge0.05$ となるので**帰無仮説を採択**します。

## R版

```R:フィッシャーの正確確率検定（R）
m=matrix(c(140, 150, 160, 180), nrow=2, byrow=T)
fisher.test(m)
```

```:実行結果

	Fisher's Exact Test for Count Data

data:  m
p-value = 0.8103
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.757838 1.454709
sample estimates:
odds ratio 
  1.049888 
```


# 結論

　PythonやRで独立性の検定を行なう場合は、**フィッシャーの直接確率検定**を利用するのが良いようです。

# 参考資料

- [1] 小島寛之 著「完全独習 統計学入門」
- [2] 大村平 著「今日から使える統計解析 普及版」
- [3] 平井明代 編著「教育・心理系研究のためのデータ分析入門」
- [4] 向後千春 著「統計学がわかる ハンバーガーショップでむり無く学ぶ、やさしく楽しい統計学」
- [5] [χ2乗検定とFisher正確確率検定　～χ2乗検定の不適切使用をしていませんか？～](https://drmagician.exblog.jp/22086293/)