Anda la gente que si viendo a ver cómo calcular el AUC (roc), que si cómo se hace en spark o que si hay que tener en cuenta muchos puntos de corte y ver las tablas de clasificación asociadas. Eso está bien para contarlo, pero no para calcularlo.
El AUC se puede considerar como la probabilidad de que el score de un “sí” elegido al azar es mayor que el score de un “no” elegido al azar. No lo digo yo, lo cuenta mucho mejor que yo , Carlos en su entrada AUC = WILCOXON. De hecho, voy a coger sus mismos datos, salvo por la semilla, que no la indica.
set.seed(45)
n <- 30
si <- data.frame(res = "si", score = rnorm(n, 1, 1))
no <- data.frame(res = "no", score = rnorm(n, 0, 1))
dat <- rbind(si, no)
Y como bien comenta Carlos, tanto Wilcoxon como el cálculo usual del AUC dan esa probabilidad. Para esto da igual que los scores sean incluso negativo, se trata de algo que da un orden.
car::some(dat)
## res score
## 1 si 1.3407997
## 2 si 0.2966597
## 7 si 0.4986218
## 9 si 2.8090374
## 12 si 1.2159889
## 34 no 0.2854323
## 40 no 0.2459699
## 48 no -0.3504094
## 53 no 0.1114906
## 60 no -0.8165108
Y copiando de su blog
test <- wilcox.test(score ~ res, data = dat)$statistic
# pongo el 1- pq salia menor que 0.5
1- test / n^2
## W
## 0.7122222
library(pROC)
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
my_roc <- roc(dat$res, dat$score)
## Setting levels: control = no, case = si
## Setting direction: controls < cases
auc(my_roc)
## Area under the curve: 0.7122
Pero también podemos hacerlo muestreando.
Nos creamos función
etiquetas <- dat$res=="si"
table(etiquetas)
## etiquetas
## FALSE TRUE
## 30 30
Ahora muestreamos con reemplazamiento los scores correspondientes a etiqueta = TRUE, es decir a los sis
pos <- sample(dat$score[etiquetas], size = 1e7, replace = TRUE)
neg <- sample(dat$score[!etiquetas], size = 1e7, replace = TRUE)
Y simplemente calculamos la probabilidad que buscamos haciendo la proporción de la veces qeu el score de un positivo gana al de un negativo.
mean(pos>neg)
## [1] 0.7122233
Y es una buena aproximación, creemos función y pongamos que en caso de empate de score, ni pa ti ni pa mi.
auc_probability <- function(labels, scores, N=1e7){
pos <- sample(scores[labels], N, replace=TRUE)
neg <- sample(scores[!labels], N, replace=TRUE)
(sum(pos > neg) + sum(pos == neg)/2) / N
}
Pues ya tenemos una forma “sencilla” de calcular auc’s, que se puede usar por ejemplo en sql.
auc_probability(etiquetas, dat$score, N= 1e6)
## [1] 0.712108
Salud y buena tarde
comments powered by Disqus