15
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-07-24

概要

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

関連エントリ

設定

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

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

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

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

カイ2乗検定(独立性の検定)

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

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

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

Pythonで実行

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

カイ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$ となるので帰無仮説を採択します。つまり、**統計学的には「実施形式」と「記入の有無」に関連性はない(それらは独立している)**と結論付けます。つまり「アンケートの自由記述欄にコメントが書かれるかどうかは、アンケートの実施形式には無関係」といえそうです。

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

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 を使って行ないました。

カイ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

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

カイ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$ 値を計算します。

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

  • 形式で記入ありの割合=(形式の割合)$\times$(記入ありの割合)
  • 形式で記入なしの割合=(形式の割合)$\times$(記入なしの割合)
  • ウェブ形式で記入ありの割合=(ウェブ形式の割合)$\times$(記入ありの割合)
  • ウェブ形式で記入なしの割合=(ウェブ形式の割合)$\times$(記入なしの割合)

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

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

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

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

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

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

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)
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)
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で独立性の検定を行なう場合は、フィッシャーの直接確率検定を利用するのが良いようです。

参考資料

15
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?