α et sont liés. Je vais essayer d'illustrer le point avec un test de diagnostic. Disons que vous avez un test de diagnostic qui mesure le niveau d'un marqueur sanguin. Il est connu que les personnes atteintes d'une certaine maladie ont des niveaux de ce marqueur inférieurs à ceux des personnes en bonne santé. Il est immédiatement clair que vous devez décider d'une valeur seuil, en dessous de laquelle une personne est classée comme «malade», tandis que les personnes dont la valeur est supérieure à cette limite sont considérées comme saines. Il est très probable, cependant, que la distribution des bloodmarker varie considérablement , même au sein des malades et en bonne santé. Certaines personnes en bonne santé peuvent avoir des niveaux de marqueurs sanguins très bas, même si elles sont parfaitement saines.β
Il y a quatre possibilités qui peuvent se produire:
- une personne malade est correctement identifiée comme malade (vrai positif = TP)
- une personne malade est faussement classée en bonne santé (faux négatif = FN)
- une personne en bonne santé est correctement identifiée comme en bonne santé (vrai négatif = TN)
- une personne en bonne santé est faussement classée comme malade (faux positif = PF)
Ces possibilités peuvent être illustrées par un tableau 2x2 :
Sick Healthy
Test positive TP FP
Test negative FN TN
α désigne le taux de faux positifs, qui est . est le taux de faux négatifs, qui est . J'ai écrit simplement un script pour illustrer graphiquement la situation.α=FP/(FP+TN)ββ=FN/(TP+FN)R
alphabeta <- function(mean.sick=100, sd.sick=10, mean.healthy=130, sd.healthy=10, cutoff=120, n=10000, side="below", do.plot=TRUE) {
popsick <- rnorm(n, mean=mean.sick, sd=sd.sick)
pophealthy <- rnorm(n, mean=mean.healthy, sd=sd.healthy)
if ( side == "below" ) {
truepos <- length(popsick[popsick <= cutoff])
falsepos <- length(pophealthy[pophealthy <= cutoff])
trueneg <- length(pophealthy[pophealthy > cutoff])
falseneg <- length(popsick[popsick > cutoff])
} else if ( side == "above" ) {
truepos <- length(popsick[popsick >= cutoff])
falsepos <- length(pophealthy[pophealthy >= cutoff])
trueneg <- length(pophealthy[pophealthy < cutoff])
falseneg <- length(popsick[popsick < cutoff])
}
twotable <- matrix(c(truepos, falsepos, falseneg, trueneg), 2, 2, byrow=T)
rownames(twotable) <- c("Test positive", "Test negative")
colnames(twotable) <- c("Sick", "Healthy")
spec <- twotable[2,2]/(twotable[2,2] + twotable[1,2])
alpha <- 1 - spec
sens <- pow <- twotable[1,1]/(twotable[1,1] + twotable[2,1])
beta <- 1 - sens
pos.pred <- twotable[1,1]/(twotable[1,1] + twotable[1,2])
neg.pred <- twotable[2,2]/(twotable[2,2] + twotable[2,1])
if ( do.plot == TRUE ) {
dsick <- density(popsick)
dhealthy <- density(pophealthy)
par(mar=c(5.5, 4, 0.5, 0.5))
plot(range(c(dsick$x, dhealthy$x)), range(c(c(dsick$y, dhealthy$y))), type = "n", xlab="", ylab="", axes=FALSE)
box()
axis(1, at=mean(pophealthy), lab=substitute(mu[H[0]]~paste("=",m, sep=""), list(m=mean.healthy)), cex.axis=1.5,tck=0.02)
axis(1, at=mean(popsick), lab=substitute(mu[H[1]]~paste("=",m, sep=""), list(m=mean.sick)), cex.axis=1.5, tck=0.02)
axis(1, at=cutoff, lab=substitute(italic(paste("Cutoff=",coff, sep="")), list(coff=cutoff)), pos=-0.004, tick=FALSE, cex.axis=1.25)
lines(dhealthy, col = "steelblue", lwd=2)
if ( side == "below" ) {
polygon(c(cutoff, dhealthy$x[dhealthy$x<=cutoff], cutoff), c(0, dhealthy$y[dhealthy$x<=cutoff],0), col = "grey65")
} else if ( side == "above" ) {
polygon(c(cutoff, dhealthy$x[dhealthy$x>=cutoff], cutoff), c(0, dhealthy$y[dhealthy$x>=cutoff],0), col = "grey65")
}
lines(dsick, col = "red", lwd=2)
if ( side == "below" ) {
polygon(c(cutoff,dsick$x[dsick$x>cutoff],cutoff),c(0,dsick$y[dsick$x>cutoff],0) , col="grey90")
} else if ( side == "above" ) {
polygon(c(cutoff,dsick$x[dsick$x<=cutoff],cutoff),c(0,dsick$y[dsick$x<=cutoff],0) , col="grey90")
}
legend("topleft",
legend=(c(as.expression(substitute(alpha~paste("=", a), list(a=round(alpha,3)))),
as.expression(substitute(beta~paste("=", b), list(b=round(beta,3)))))), fill=c("grey65", "grey90"), cex=1.2, bty="n")
abline(v=mean(popsick), lty=3)
abline(v=mean(pophealthy), lty=3)
abline(v=cutoff, lty=1, lwd=1.5)
abline(h=0)
}
#list(specificity=spec, sensitivity=sens, alpha=alpha, beta=beta, power=pow, positiv.predictive=pos.pred, negative.predictive=neg.pred)
c(alpha, beta)
}
Regardons un exemple. Nous supposons que le niveau moyen du marqueur sanguin chez les personnes malades est de 100 avec un écart-type de 10. Chez les personnes en bonne santé, le niveau sanguin moyen est de 140 avec un écart-type de 15. Le clinicien fixe le seuil à 120.
alphabeta(mean.sick=100, sd.sick=10, mean.healthy=140, sd.healthy=15, cutoff=120, n=100000, do.plot=TRUE, side="below")
Sick Healthy
Test positive 9764 901
Test negative 236 9099
Vous voyez que les zones ombrées sont en relation les unes avec les autres. Dans ce cas, et . Mais que se passe-t-il si le clinicien a fixé le seuil différemment? Fixons-le un peu plus bas, à 105 et voyons ce qui se passe.α=901/(901+9099)≈0.09β=236/(236+9764)≈0.024
Sick Healthy
Test positive 6909 90
Test negative 3091 9910
Notre est très bas maintenant car presque aucune personne en bonne santé n'est diagnostiquée malade. Mais notre a augmenté, car les personnes malades avec un niveau de marqueur sanguin élevé sont désormais faussement classées comme saines.αβ
Enfin, regardons comment et changent pour différents seuils:αβ
cutoffs <- seq(0, 200, by=0.1)
cutoff.grid <- expand.grid(cutoffs)
plot.frame <- apply(cutoff.grid, MARGIN=1, FUN=alphabeta, mean.sick=100, sd.sick=10, mean.healthy=140, sd.healthy=15, n=100000, do.plot=FALSE, side="below")
plot(plot.frame[1,]~cutoffs, type="l", las=1, xlab="Cutoff value", ylab="Alpha/Beta", lwd=2, cex.axis=1.5, cex.lab=1.2)
lines(plot.frame[2,]~cutoffs, col="steelblue", lty=2, lwd=2)
legend("topleft", legend=c(expression(alpha), expression(beta)), lwd=c(2,2),lty=c(1,2), col=c("black", "steelblue"), bty="n", cex=1.2)
Vous pouvez immédiatement voir que le rapport de et n'est pas constant. Ce qui est également très important, c'est la taille de l'effet. Dans ce cas, ce serait la différence des moyennes des niveaux de marqueurs sanguins chez les personnes malades et en bonne santé. Plus la différence est grande, plus les deux groupes peuvent être facilement séparés par une coupure:αβ
Ici, nous avons un test "parfait" dans le sens où le seuil de 150 discrimine les malades des sains.
Ajustements de Bonferroni
Les ajustements de Bonferroni réduisent l' erreur mais gonflent l'erreur de type II ( ) . Cela signifie que l'erreur de prendre une décision faussement négative est augmentée tandis que les faux positifs sont minimisés. C'est pourquoi l'ajustement de Bonferroni est souvent appelé conservateur. Dans les graphiques ci-dessus, notez comment le augmenté lorsque nous avons abaissé le seuil de 120 à 105: il est passé de à . Dans le même temps, passé de à .αββ0.020.31α0.090.01