帰無仮説検定で有意になった項目についてROC 解析をしてください

MikuHatsune2018-03-08

と査読で言われた。
 
状況設定としてはこんな感じである。いま、とある検査項目X (連続量)について、予後を予測するマーカーになるか検討したい。ここで、デザインとしてはとりあえず研究を立ち上げてみました、というような後ろ向き観察研究で、予後転帰が確定している症例について、診断確定時の検査値を取ってきた、という状況である。ここで、サンプル数は予後が良かった群も悪かった群も20 くらいである。
X 以外にも、40個くらいの項目がとってある。というのも、これらは「取れるから取った」だけの値であり、これらによって予後が予測できるかというと、3個くらいは、確実に予後に関連していると言われているものがあるが、ほかはあっ(察し)という感じである。
 
注目している検査項目X が、ROCAUC 0.75 くらいだった、としよう。他の40個近くの検査項目は、患者背景のばらつきを検定してください、と言われているので、何も考えずtでもwilcox でもカイ自乗でもいいので検定するのだが、無作為抽出・割付した研究ではないので、当然、いくつかは有意差がある。
 
査読者が言うには、これらの有意な検査項目と、新規マーカーX を比較して、X が有意にマーカーなり得るか検討しろ、ということらしい。
いまいち腑に落ちなかったのでシミュレーションで考えてみる。
 
いま、査読者が言っていることで疑問に思っているのが、ある検査項目T に着目した時、1番目の群の検査結果T_1 と対照となる群T_2 について
 
・2群間で分布が異なっていること(患者背景で有意差があるかどうか、について言っている)
・分布が異なるとき、2群の判別性能をROC で評価するとどうなるのか
 
ということでいいと思われる。
 
まず、T_1T_2 には差がない(と神様だけが知っている)とき、帰無仮説検定では有意水準\alpha だけ、有意な結果を生じる。
どちらも平均0、分散1 の正規分布から、2群分適当にランダムサンプリングでデータを作り、この標本について、t検定とROC 解析をしてp値とAUC の値を記録する。
差がないときのシミュレーション結果は、図の緑点である。p=0.05 のところにタテ線を引いた。
2群には差がないとわかっているにもかかわらず、偶然にもp<0.05 になり有意になってしまった結果については、ROCAUC は0.7 相当ある。
有意にならなかった場合でも、ROCAUC は0.6くらいは出てしまう。

 
さて、査読者はご丁寧にも、「ROC 解析のAUC は、0.7 程度で有用な判別性能があると言われています」というようなご高説を賜ってくださったので、これから鑑みるに、2群の間に差がないデータでも、有用な判別性能を持つ場合があるので、患者背景で大量に検定した結果についてROC 解析をやるべき、と言っているのであろう()
 
次に、T_1T_2 には差がある(と神様だけが知っている)ときを考える。ここで、2群には1 の差がある(両群とも分散1)と設定したとき、検出力は0.84 程度になることが計算でわかる。
このときの結果が図の青点である。差がない場合よりも、小さいp 値が出やすいので青点は左に偏っている。
しかし、AUC については0.7 程度が最も密度が高い。しかも、差がない緑に比べてAUC が高い傾向にあるのかというと、そうでもないのでAUC に対して効果量は影響しなさそう。
 
となると、帰無仮説検定を絨毯爆撃して有意な項目についてROC 解析をすると、AUC 0.7 のような有用() な結果になってしまいがちな感じがするのだが、査読者がそうのたまう()のでやった()

library(pROC)
N <- c(20, 18)
alpha <- 0.05

niter <- 10000

# 差がない
res <- matrix(0, niter, 2)
for(i in seq(niter)){
  g <- unlist(mapply(rep, 1:2, N))
  d <- unlist(mapply(rnorm, n=N, m=0))
  res[i, 1] <- t.test(d ~ g)$p.value
  res[i, 2] <- roc(g, d)$auc
}

# 差がある
res1 <- matrix(0, niter, 2)
M <- c(1, 0)
for(i in seq(niter)){
  g <- unlist(mapply(rep, 1:2, N))
  d <- unlist(mapply(rnorm, n=N, m=M))
  res1[i, 1] <- t.test(d ~ g)$p.value
  res1[i, 2] <- roc(g, d)$auc
}
mean(res1[,1] < alpha)


r <- rbind(res, res1)
cols <- c(rgb(0, 1, 0, 0.3), rgb(0, 0, 1, 0.3))
xl <- c(0, 1)
yl <- range(r[,2], 1)
plot(r, col=rep(cols, each=niter), pch=16, cex=0.7, xlab="p value", ylab="AUC", xlim=xl, ylim=yl)
abline(v=alpha, h=0.5, lty=3)
legend("topright", legend=c(expression(Delta==0), expression(Delta==1)), col=cols, pch=16, cex=2)