予後因子 prognostic と予測因子 predictive は何が違うのか

MikuHatsune2017-12-12

興味深い話を教えてもらったので読んだ。
Understanding Prognostic versus Predictive Biomarkers
 
よく予後因子や予測因子となるバイオマーカーを探そう、という研究があるが、そもそも予後因子/予測因子とはなんぞや、という話。
現実世界においては、あるバイオマーカーがあったときに、厳密に予後因子であるか予測因子であるかは分けられないが、概念的には両者は異なる。
本文中では、

To identify a predictive biomarker, there generally should be a comparison of a treatment to a control in patients with and without the biomarker.

the biomarker illustrated in Figures 1A and 1B is prognostic but not predictive and will not be helpful in choosing between standard and experimental therapy.

とあるので、統計素人の理解としては、
臨床研究は新薬 vs 標準治療(もしくはプラセボ)の比較なので、比較した群において差があるかどうかを左右する因子であることが予測因子 predictive。比較しない群で(生存に)差があるかどうかが予後因子 prognostic。
因子のある/なしで、新薬を使うか標準治療を使うかの判断に影響するのが予測因子 predictive。
と思った。
 
例えばよく誤解されやすいのが、あるバイオマーカー(BM)のある/なしで、新薬 TRT+ (TRT- は標準治療でもプラセボでもなんでもいいが、とにかく比較される対照)についてこんなに差があったとする。(Fig 1A)

このとき、BM のある/なしで生存に差があるから、BM を確認することで予後が予測できる、と思ってしまう。このとき、BM は予後因子ではあるが予測因子ではない。
 
なぜかというと、臨床研究はそもそも、新薬 vs 対照の比較研究だからである。BM のある/なしによる生存の差は検討課題ではない。実際の臨床研究の設定として、新薬 TRT+ と対照 TRT - の比較を、BM のある/なしで層別化したらこんな感じになる。
ここで、BM のある/なしは黒赤で、TRT は実線/破線で2x2 になっている。plot の重なりをずらすために値が微妙に変えてあるが、本質的には重なっていると思ってよい。(Fig 1B)

さてここで、TRT + の集団に限ってみれば、BM のある/なしは生存に差があった。しかし、TRT - を見ても、BM のある/なしはTRT + の生存の差と同じ程度に生存に差が出るようになっている。
つまり、TRT + にしようがTRT - にしようが、BM によって生存に差が(ほぼ同等に)出るようになる。なので、BM があろうがなかろうが、「TRT + かTRT - にすべきかどうか」は悩む必要はないのである。だが、BM を見れば、その人が長生きしそうか、しなさそうなのかの「予後」には影響する。なのでこの状況ではTRT +/- の比較はされていないし、予後因子になるのである。
 
4本も直線があるとわかりにくいので、ばらばらに描いてみる。ここで予後因子らしさを出しているのは黄色のマスである。いま、TRT + の集団において、BM のある/なしは生存に影響しており、また、TRT - の集団においても、M のある/なしは生存に影響している
しかし、色のついていないマスをみると、BM がある集団に対してTRT + とTRT - は差がない。BM がない集団も同様である。臨床研究で比較研究しているのはこの状況であるので、BM のステータスはTRT の選択に影響しないから、TRT の選択結果(未来)を予測しない。たぶん。

 
予測因子の話になるが、予後因子の最初の図とは対照的に、一見して予後にも予測にも役に立たなさそうな場合はある。これは、TRT + の集団においてBM のある/なしが生存に影響していない。(Fig 2A)

 
しかしながら、何度も言うように、臨床研究は新薬 vs 対照の比較研究なので、TRT - が登場しないと結論は導けない。ここで、こんな感じの図になると、これは予測因子となる。(Fig 2B)

 
少しややこしいので、先に2x2 に分割する。予測因子で注目するのは緑のマスである。いま、ひだり上のTRT + の集団においては、BM のある/なしは生存に影響しなかったが、みぎ下(予後因子では黄色にしていたマス)のTRT - の集団においてはBM のある/なしで生存に差があるので、これは実は予後因子でもある。しかし、TRT + とTRT - の比較はされていない。
注目すべきはひだり下の緑マスである。BM がない集団においては、TRT + とTRT - の生存に差がある。
みぎ上の緑マスは、BM がある集団において、TRT + とTRT - は差がない。
つまり、BM がない、と判定された集団においては、TRT の選択が生存に影響する。これが予測因子である。BM がある集団は、TRT の選択に関係がないが、TRT がない集団はTRT を選択しなければ生存が伸びない。というわけで選択を迫られる因子が予測因子である。たぶん。

 
BM の付け方を逆にしてしまったので本文のbiomarker positive/negative は逆に読み替えてください。

# 生存曲線を適当に
x <- seq(0, 5, length=3000)
surv <- function(m){
  exp(-log(2)/m * x)
}

# plot 用
xl <- range(x)
yl <- c(0, 1)
m <- c(8, 3, 8.0-0.5, 3-0.3)
cols <- c("black", "red")
lty <- c(1, 3)
PN <- c("+", "-")
i <- c(1, 2, 1, 2)
j <- c(1, 1, 2, 2)


# prognostic
par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT +", PN), lty=lty[1], lwd=3, col=cols, text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)


# 2x2 comparison
par(mfrow=c(2, 2))
par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
polygon(par()$usr[c(1,2,2,1)], par()$usr[c(3,3,4,4)], col="yellow")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
#lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
#lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
#lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
#lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
#lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
#lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
polygon(par()$usr[c(1,2,2,1)], par()$usr[c(3,3,4,4)], col="yellow")
#lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
#lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)


# predictive
par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[3]), lwd=3, lty=lty[1], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT +", PN), lty=lty[1], lwd=3, col=cols, text.font=2)

m[2] <- m[1] - 0.3
par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

# 2x2 comparison
par(mfrow=c(2, 2))
par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
#lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
#lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
polygon(par()$usr[c(1,2,2,1)], par()$usr[c(3,3,4,4)], col="lightgreen")
lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
#lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
#lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
polygon(par()$usr[c(1,2,2,1)], par()$usr[c(3,3,4,4)], col="lightgreen")
#lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
#lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)

par(mar=c(4, 5, 2, 2), las=1, cex.axis=1.5, cex.lab=1.5)
plot(0, type="l", xlim=xl, ylim=yl, lwd=4, xlab="Time", ylab="Survival")
#lines(x, surv(m[1]), lwd=3, lty=lty[1], col=cols[1])
#lines(x, surv(m[2]), lwd=3, lty=lty[1], col=cols[2])
lines(x, surv(m[3]), lwd=3, lty=lty[2], col=cols[1])
lines(x, surv(m[4]), lwd=3, lty=lty[2], col=cols[2])
legend("bottomleft", legend=sprintf("BM %s;\tTRT %s", PN[j], PN[i]), lty=lty[i], lwd=3, col=cols[j], text.font=2)