McNemar検定

McNemar検定と2項検定

McNemar(マクネマー,マクニマー,頭の「マ」にアクセント)検定は,対応のある $t$ 検定に似ていますが,結果が2値(「なし」と「あり」)に限られる場合に使います。

例えば,20人にプリテスト・ポストテストを受験させ,合格・不合格を調べたところ,次のようになったとします:

合格不合格
プリテスト713
ポストテスト146

プリテスト合格者は7人でしたが,ポストテスト合格者は14人に増えたので,成績は向上したように見えます。でも,フィッシャーの検定

fisher.test(matrix(c(7,14,13,6), nrow=2))

をしてみると,$p = 0.05616$ ですので,5%水準で有意ではありません。

ところが,プリテスト受験者とポストテスト受験者は同じ20人ですので,よく内訳を調べてみると,次のようになっていました:

ポストテスト合格ポストテスト不合格
プリテスト合格61
プリテスト不合格85

プリテスト・ポストテストの両方に合格した人や,両方に不合格だった人は,変化がないので,除外して考えます。重要なのは,不合格から合格に転じた人が8人もいるのに対して,合格から不合格に転じた人は1人しかいないということです。

McNemar検定は,「どちらも合格」「どちらも不合格」を無視して,「不合格→合格」8人と「合格→不合格」1人の違いが有意かどうかを調べる検定です。

元々のMcNemar検定(Rの mcnemar.test())は $\chi^2$ 検定を使うのですが,よく考えてみると,8人と1人の違いの検定は,「硬貨を9回投げて表が8回,裏が1回出たが,硬貨は大丈夫か」という2項検定のほうが厳密に計算できそうです:

> binom.test(1, 9)  # binom.test(8, 9) でも同じ

	Exact binomial test

data:  1 and 9
number of successes = 1, number of trials = 9, p-value = 0.03906
alternative hypothesis: true probability of success is not equal to 0.5
95 percent confidence interval:
 0.002809137 0.482496515
sample estimates:
probability of success 
             0.1111111 

$p = 0.03906$ で,5%水準で有意になりました。

元々のMcNemar検定は次のようになります:

> mcnemar.test(matrix(c(6,8,1,5), nrow=2))

	McNemar's Chi-squared test with continuity correction

data:  matrix(c(6, 8, 1, 5), nrow = 2)
McNemar's chi-squared = 4, df = 1, p-value = 0.0455

デフォルトは連続性の補正をします。補正をしないなら correct=FALSE オプションを与えます。連続性の補正をする・しないの区別はややこしいので,余計なことを考える必要のない厳密な2項検定による方法がお薦めです。

要するに,McNemar検定は,「不合格」を0,「合格」を1として,ポストテストとプリテストの差を符号検定していることにあたります。

符号検定の代わりにt検定を使うことも可能です。そうすれば,「変化なし」の情報も捨てる必要はありません:

t.test(c(rep(0,11),rep(1,8),rep(-1,1)))  # 変化なし11個,1増8個,1減1個

$p = 0.01527$ となります。

そもそも,「合格」「不合格」の2値ではなく,成績の測定をしっかりすれば,大手を振って,対応のある $t$ 検定を使うことができます。逆に,「成績が正規分布していないっぽい」などという懸念から $t$ 検定をやめて上位群・下位群に2分してMcNemar検定を使うのなら,残念です。

mcnemar.exact() によるMcNemar検定

本質的には以上で説明したことで尽きていますが,オッズ比とその信頼区間も求める方法として,ここではexact2x2パッケージの mcnemar.exact() を使う方法を説明します。まずは(まだインストールしていないなら)exact2x2パッケージをインストールし,ライブラリとして読み込みます:

install.packages("exact2x2")
library(exact2x2)

使い方は,次のように分割表を行列の形で与えます:

> mcnemar.exact(matrix(c(6,8,1,5), nrow=2))

	Exact McNemar test (with central confidence intervals)

data:  matrix(c(6, 8, 1, 5), nrow = 2)
b = 1, c = 8, p-value = 0.03906
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.00281705 0.93235414
sample estimates:
odds ratio 
     0.125 

2項検定のときと同じ $p$ 値 0.03906 が得られました。また,オッズは 1:8 ですので 0.125 ですが,効果がない場合のオッズ 1:1 と比較して,オッズ比も 0.125 になり,その95%信頼区間が $[0.003, 0.932]$ であることもわかります。

mcnemar.exact()binom.test() ではなくexactciパッケージの binom.exact() を使っています。でもこれは binom.test() より binom.exact() のほうが正確だというわけではなく,方法が違っているだけです。両者の違いについては検定と区間推定の最後のところでも説明しました。


Last modified: