¿Qué tal lo he hecho en mi oposición? - cálculo de percentiles y estadística descriptiva básica
Introducción
Voy a aprovechar una pequeña consulta que me han hecho para explicar cómo se calcula el percentil para datos agrupados en R. Haremos lo siguiente:
- Nos descargaremos las la lista de admitidos y la de aprobados de una oposición, con miles de personas.
- Filtraremos el fichero para dejar sólo las notas.
- Veremos el histograma, mediana, outliers etc de los datos.
- Calcularemos el percentil de la nota que nos interesa, en este caso un 65.
Con esta información, podremos responder a la pregunta planteada inicialmente sobre el rendimiento en el exámen.
La parte estadística es sencilla. Lo más engorroso de este trabajo es descargar y limpiar los datos hasta conseguir algo aceptable. Pero esto también es una parte importante de la ciencia de datos (los ficheros no los suelen mandar limpios)
Descarga de los datos del problema
Ficheros para descargar
click aquí->relación de aprobados.
click aquí->relación de admitidos
La relación de admitidos sólo la queremos para contar cuántos se presentaban al exámen, por mera curiosidad y aunque no forme parte de la pregunta inicial. Son 114 páginas y cada página con 51 personas (salvo la última, pero la diferencia es poca en un número tan grande). Así que el total de admitido lo calculamos como:
admitidos<-51*114
cat("admitidos=",admitidos)
## admitidos= 5814
Filtrado del fichero
Tras descargar el fichero de aprobados lo primero que haremos será dejar una única columna con las notas. Esto se puede hacer de mil formas, así que pondré aquí la que me ha salido a mí. Lo primero sería copiar & pegar del pdf de descarga a un txt todo, sin discriminar, y entonces podemos empezar a filtrar:
filename<-"aprobados.txt"
a<-paste(readLines(filename,encoding="UTF-8"),collapse=" ") # todo en un string gigante
El objeto a contiene una mezcla de todo tipo de datos alfanuméricos mezclados con los valores que buscamos. Con una serie de substituciones vamos a cribar todo para dejar sólo los números de la forma dd.dd (dos decimales)
a<-gsub(',','.',a) # punto en lugar de coma en los decimales
a<-gsub('\\*\\*\\*[0-9][0-9][0-9][0-9]\\*\\*','',a) # quitar ***NNNN**
a<-gsub('[A-Z]','',a) #quitar a-zA-Z
a<-gsub('[a-z]','',a)
a<-gsub('\t',' ',a)
a<-gsub('Ó','',a)
a<-gsub('Ñ','',a)
a<-gsub(' . ',' ',a); a<-gsub(' . ',' ',a) #punto sueltos
a<-gsub(' ',' ',a)
Ahora, transformaremos el mega-string en un vector de strings, separados por los espacios, y nos quedaremos sólo con los string que tengan longitud 5, que es la longitud de un número decimal del tipo “dd.dd”.
#transformar datos en vector de números con las notas
notas<-strsplit(a,split=" ") #seperate integers by whitespaces
notas<-notas[[1]]
notas<-notas[notas!=""]
library(stringi)
notas<-subset(notas,stri_length(notas)==5) #dd.dd tiene longitud 5
notas<-as.double(notas)
# podemos comprobar que está todo en orden
head(notas,6)
## [1] 62.33 81.00 58.00 53.67 77.00 54.67
Un primer vistazo a los datos
Ante de abordar cualquier problema, del tipo que sea, lo primero es echarle un ojo al histograma para hacernos una idea de cómo se distribuyen lo datos. Notar que hemos elegido un numero de clases para el histograma mayor que el elegido por R por defecto para darle mayor precisión y que aparezcan las notas más elevadas, a la derecha del gráfico. Marcamos con una línea vertical roja la nota sobre la que nos están preguntando y con una verde la mediana de los aprobados.
hist(notas,breaks=15,col="peachpuff", main="NOTAS DE LOS APROBADOS",border="black")
abline(v=65, col="red",lwd=2)
abline(v=median(notas),col="green",lwd=2)
Como puede verse, los datos tienen una gran asimetría a derecha, que es
lógico dado que cada vez va siendo más y más difícil mejorar la nota que
uno saca en este tipo de exámenes, dada la gran profundidad del temario
y la “manía” de los tribunales de poner exactamente dos preguntas por
tema.
La nota de corte es el mínimo del gráfico:
min(notas)
## [1] 49.33
Y podemos ver también las 10 notas más altas, a partir de la cual se calcula la nota de corte tomando el 60% de su promedio
head(sort(notas,decreasing=TRUE),10)
## [1] 82.67 81.00 77.00 76.00 74.33 72.33 71.00 70.00 69.33 66.67
En el caso de datos tan sesgados no tiene interés la media, sino la mediana. En este caso es el valor marcado arriba con una línea verde, a la derecha del cual se encuentra nuestra nota (rojo):
median(notas)
## [1] 57.33
Tener en cuenta que esta es la mediana de los aprobados. La única información que tenemos de los supensos es cuántos son, pero nada más.
Con un boxplot veremos no sólo la mediana sino también posibles outliers:
boxplot(notas,col="blue",horizontal = TRUE, main="NOTAS DE LOS APROBADOS")
Han aparecido unos cuantos outliers en las notas. Veamos cuáles son:
#calculamos la frontera para los outliers (Q3+1.5 IQR)
Q1<-quantile(notas,.25)
Q3<-quantile(notas,.75)
IQR<-Q3-Q1 #rango intercuartilico
Y listamos los outliers, que son aquellos >Q3+1.5*IQR:
outliers<-which(notas>(Q3+1.5*IQR))
notas[outliers]
## [1] 81.00 77.00 76.00 82.67
De nuevo, insistiré en que esto está siendo calculado de acuerdo con la distribución de aprobados, dado que no tenemos información sobre los suspensos salvo su número.
Las notas sobre las que se calcula el corte son casi todas outliers (es bastante lógico que así sea y también es lógico que que la nota de corte salga por debajo del 50).
El percentil asociado a sacar un “65”
Vamos a responder a la pregunta que teníamos en un principio. ¿Qué tal nota es un 65?
Evidentemente, respecto de los suspensos muy buena. Pero no sabemos si la gente que ha suspendido se ha presentado o no, si ha estudiado o ha ido sin prepararse. Es más interesante preguntarse qué tal es respecto de la gente que ha aprobado. ¿Cómo de bueno es un 65?
# número de aprobados
naprobados<-length(notas)
cat("número de aprobados",naprobados)
## número de aprobados 103
#número de notas <= 65
nmenores<-length(subset(notas,notas<=65))
cat("número de notas menores que 65:", nmenores)
## número de notas menores que 65: 85
#percentil
cat("nuestro percentil=", round(100*(nmenores/naprobados),0) )
## nuestro percentil= 83
Así pues, un 65, aunque no lo parecía en el gráfico es una nota muy buena, lo cual responde a nuestra pregunta inicial.
Comentarios
Publicar un comentario