いわゆる「厳密検定」または「順列検定」の逆説的な振る舞いに出会いました。その原型はフィッシャー検定です。ここにあります。
400人の個人の2つのグループ(例:対照400例と例400)があり、2つのモダリティ(例:曝露/非曝露)の共変量があるとします。露出した個人は5人だけで、すべて2番目のグループです。フィッシャーテストは次のようになります。
> x <- matrix( c(400, 395, 0, 5) , ncol = 2)
> x
[,1] [,2]
[1,] 400 0
[2,] 395 5
> fisher.test(x)
Fisher's Exact Test for Count Data
data: x
p-value = 0.06172
(...)
しかし今、2番目のグループ(症例)には、疾患の形態や求人センターなど、いくつかの不均一性があります。それは100人の4グループに分けることができます。このようなことが起こりそうです:
> x <- matrix( c(400, 99, 99 , 99, 98, 0, 1, 1, 1, 2) , ncol = 2)
> x
[,1] [,2]
[1,] 400 0
[2,] 99 1
[3,] 99 1
[4,] 99 1
[5,] 98 2
> fisher.test(x)
Fisher's Exact Test for Count Data
data: x
p-value = 0.03319
alternative hypothesis: two.sided
(...)
これは単なる例です。しかし、最初の400人の個人では、曝露の頻度は0であり、残りの400人では0.0125であると想定して、2つの分析戦略の検出力をシミュレートできます。
400人の2つのグループを使用して、分析の能力を推定できます。
> p1 <- replicate(1000, { n <- rbinom(1, 400, 0.0125);
x <- matrix( c(400, 400 - n, 0, n), ncol = 2);
fisher.test(x)$p.value} )
> mean(p1 < 0.05)
[1] 0.372
そして、400人の1グループと100人の4グループ:
> p2 <- replicate(1000, { n <- rbinom(4, 100, 0.0125);
x <- matrix( c(400, 100 - n, 0, n), ncol = 2);
fisher.test(x)$p.value} )
> mean(p2 < 0.05)
[1] 0.629
パワーにはかなりの違いがあります。ケースを4つのサブグループに分割すると、これらのサブグループ間に分布の違いがなくても、より強力な検定が得られます。もちろん、この電力の増加は、タイプIのエラー率の増加によるものではありません。
この現象はよく知られていますか?それは、最初の戦略が不十分であるということですか?ブートストラップされたp値はより良い解決策でしょうか?コメントは大歓迎です。
後記
これが私のコードです。
B <- 1e5
p0 <- 0.005
p1 <- 0.0125
# simulation under H0 with p = p0 = 0.005 in all groups
# a = 2 groups 400:400, b = 5 groupe 400:100:100:100:100
p.H0.a <- replicate(B, { n <- rbinom( 2, c(400,400), p0);
x <- matrix( c( c(400,400) -n, n ), ncol = 2);
fisher.test(x)$p.value} )
p.H0.b <- replicate(B, { n <- rbinom( 5, c(400,rep(100,4)), p0);
x <- matrix( c( c(400,rep(100,4)) -n, n ), ncol = 2);
fisher.test(x)$p.value} )
# simulation under H1 with p0 = 0.005 (controls) and p1 = 0.0125 (cases)
p.H1.a <- replicate(B, { n <- rbinom( 2, c(400,400), c(p0,p1) );
x <- matrix( c( c(400,400) -n, n ), ncol = 2);
fisher.test(x)$p.value} )
p.H1.b <- replicate(B, { n <- rbinom( 5, c(400,rep(100,4)), c(p0,rep(p1,4)) );
x <- matrix( c( c(400,rep(100,4)) -n, n ), ncol = 2);
fisher.test(x)$p.value} )
# roc curve
ROC <- function(p.H0, p.H1) {
p.threshold <- seq(0, 1.001, length=501)
alpha <- sapply(p.threshold, function(th) mean(p.H0 <= th) )
power <- sapply(p.threshold, function(th) mean(p.H1 <= th) )
list(x = alpha, y = power)
}
par(mfrow=c(1,2))
plot( ROC(p.H0.a, p.H1.a) , type="b", xlab = "alpha", ylab = "1-beta" , xlim=c(0,1), ylim=c(0,1), asp = 1)
lines( ROC(p.H0.b, p.H1.b) , col="red", type="b" )
abline(0,1)
plot( ROC(p.H0.a, p.H1.a) , type="b", xlab = "alpha", ylab = "1-beta" , xlim=c(0,.1) )
lines( ROC(p.H0.b, p.H1.b) , col="red", type="b" )
abline(0,1)
結果は次のとおりです。
したがって、同じ真のタイプIのエラーでの比較でも、(実際にははるかに小さい)差が生じることがわかります。