R とエクセルで解析結果が違うんですがどうしたらいいですか?

MikuHatsune2016-10-24

という質問を同級生から受けた。
氏いわく、リスクの有無と疾患の有無で分割表をフィッシャー検定したら、R ではp=1 でエクセルではp=0.7 だった。たぶんp=0.7 っぽいからエクセルの解析を信じたいのだけど、なぜR でp=1 になったのか、とのこと。
そしてその分割表データとRスクリプトが添付されてた。

b2 <- matrix(c(14, 21, 10, 17), 2)
fisher.test(b2)
	Fisher's Exact Test for Count Data

data:  b2
p-value = 1
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.3588741 3.6373238
sample estimates:
odds ratio 
  1.131049 

R でやったんならR が正しいだろ…と思ったが、それはそれでR 盲信者だということに反省したので、原点に立ち返って定義からやってみる。
 
確率の基本は、受験数学では全通りの数え上げである。フィッシャーの正確確率検定
\begin{matrix} & B_1&B_2&&\\A_1&a&b&e\\A_2&c&d&f\\&g&h&n\end{matrix}
という分割表において
P=\frac{_eC_a _fC_c}{_nC_g}=\frac{e!f!g!h!}{n!a!b!c!d!}
で与えられる。
上の分割表は、自由度1、すなわち、\Delta という整数がひとつ動くと、周辺度数を満たすためには他すべてが連動して動く。
\begin{matrix} & B_1&B_2&&\\A_1&a-\Delta&b+\Delta&e\\A_2&c+\Delta&d-\Delta&f\\&g&h&n\end{matrix}
すべてのセルは0 以上だから、考えられる表のパターンはいかの通り。

idx <- matrix(c(1, -1, -1, 1), 2)
i <- -14:10
bs <- mapply(function(z) b2 + idx*z, i, SIMPLIFY=FALSE)

各々の分割表の確率を計算すれば、「考えられるすべての分割表」は数え上げられているので、確率の和は1になる。

f <- function(mat) choose(sum(mat[1,]), mat[1,1])*choose(sum(mat[2,]), mat[2,1])/choose(sum(mat), sum(mat[,1]))
p <- sapply(bs, f) # Fisher exact probability
plot(p, type="s", ylab="probability", main="Fisher exact probability", lwd=5)
abline(v=15, lty=3, lwd=3)


 
b2 の分割表は15番目で、これはもっとも「起こりうりそう」な分割表なので、これより生起確率の小さい分割表の確率(b2 自身を含む)を足すと、確率1 になる。
というわけで、たとえば片側検定をしようとして、fisher.test のalternative にless もしくはgreater を指定して、15番目より小さい確率もしくは大きい確率を足してみると、一致していることがわかる。

fisher.test(b2, alternative="less")$p.value; sum(p[1:15])
fisher.test(b2, alternative="greater")$p.value; sum(p[15:length(p)])

 
というわけで、R でやったのがやはりよかった。
 
逆に、エクセルでなぜp=0.7 になったのかが再現性がまったくないのでわからない。エクセルでフィッシャー検定をしようとするとエクセル統計のアドインが必要っぽいので、氏が持っていたとは到底思えないので謎。