Saltar al contenido

Indice / Practicas / EJ-8.2

EJ-8.2 · Distribucion de notas como tabla de conteos

Un histograma es una tabla de conteos dibujada. Acá se pide la tabla, porque la tabla es lo que se puede comparar, citar y discutir. El dibujo sale solo después.

Qué hay que hacer

A partir de estudiantes_notas.csv, producir dos archivos:

Y además, aunque no se compare: el histograma de las tres notas, con los mismos bordes en los tres, guardado como PNG.

ELI5Explicado facil

Es agrupar a los alumnos por nota: los que sacaron entre 3 y 4 en un montón, entre 4 y 5 en otro, y así hasta el 10. Después se cuenta cuántos hay en cada montón.

Lo que hay que decidir es qué hacer con los que no tienen nota, y con uno que tiene un 99. Ninguno de los dos entra en un montón, y ninguno de los dos se puede tirar sin dejar constancia.

Archivos

Los tramos vacíos van igual

Nadie sacó menos de 3 en ninguna de las tres notas, así que los tramos de 0 a 3 tienen cero alumnos. Esas filas se escriben igual, con un 0. Una tabla de histograma a la que le faltan tramos no se puede dibujar sin adivinar cuáles faltan, y dos personas correctas producirían archivos distintos.

La comprobación de treinta segundos

El archivo tiene 40 filas por 3 notas, o sea 120 celdas. Al terminar: la suma de la columna alumnos más la cantidad de filas descartadas tiene que dar exactamente 120.

Si da menos, hay observaciones desapareciendo en silencio, que es la forma en que falla casi siempre un histograma. Si da más, estás contando alguna dos veces.

Cómo saber si te salió

python comparar.py mi_distribucion.csv distribucion_notas.csv

Si no dice nada, tu archivo es idéntico al esperado. Si difiere, te dice qué fila y qué columna.

Antes de arrancar, mirá los datos

estudiantes_notas.csv (entrada) · 40 filas, se muestran 5
legajoestudiantenota_1nota_2nota_3
L2601Karina Acosta9.74.78.6
L2602Santiago Ramos6.03.84.2
L2603Carla Luna8.13.63.8
L2604Lucas Núñez7.37.43.4
L2605Tamara Torres9.59.57.8

El contrato de salida

distribucion_notas.csv · 30 filas

ColumnaTipoQue lleva
notatextonota_1, nota_2 o nota_3
desdeenteroExtremo inferior del tramo, incluido
hastaenteroExtremo superior del tramo, excluido salvo en el ultimo tramo
alumnosenteroCuantas notas validas caen en ese tramo

Orden de las filas: nota ascendente, y dentro de cada nota desde ascendente. El par (nota, desde) es unico. Indice: no se escribe: to_csv(index=False)

notas_descartadas.csv · 9 filas

ColumnaTipoQue lleva
legajotextoEl legajo del estudiante
notatextoCual de las tres columnas
valortextoEl valor tal cual viene en el archivo; para un campo vacio, la palabra vacio
motivotextoUno del vocabulario cerrado de motivos

Orden de las filas: legajo ascendente, y dentro de cada legajo nota ascendente. El par (legajo, nota) es unico. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
los diez tramos siempre estan, aunque no tengan a nadienota_2 no tiene a nadie entre 0 y 3, por ejemploescribir escribir la fila con alumnos = 0. Una tabla de histograma con tramos faltantes no se puede dibujar sin adivinar cuales faltandistribucion_notas.csv
tokens de ausente en nota_33 celdas: una vacia, una con N/A y una con NaNdescartar descartar ese valor, no la fila: las otras dos notas del mismo estudiante siguen contandonotas_descartadas.csv con motivo ausente; el valor se informa tal cual vino, y la celda vacia se escribe 'vacio' para que no quede un campo vacio en el objetivo
el token '-' en nota_32 celdasdescartar descartar ese valor. El guion es uno de los cuatro tokens de ausente del corpus, junto con NaN, N/A y nullnotas_descartadas.csv con motivo ausente y valor '-'
notas mayores que 103 celdas: 12.5 y 10.5 en nota_1, y 99.0 en nota_2descartar descartar el valor. El dominio de una nota de este curso es de 0 a 10 inclusivenotas_descartadas.csv con motivo fuera_de_rango
nota negativa1 celda: -1.0 en nota_3descartar descartar el valor, por el mismo dominionotas_descartadas.csv con motivo fuera_de_rango
el 10.0 exactono aparece en estos datos y hay que decidirlo igualun un 10 va en el ultimo tramo, el de 9 a 10, que es el unico con los dos extremos incluidosdistribucion_notas.csv
Orden de comprobacion

Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:

  1. convertir las tres columnas a numero con errors='coerce'
  2. anotar los descartes por ausente y por fuera de rango, con el valor original
  3. contar por tramo lo que quedo, con los diez tramos siempre presentes
  4. ordenar las dos salidas

El valor original hay que leerlo antes de convertir: despues de to_numeric, el guion y el campo vacio son los dos NaN y ya no se distinguen. Por eso el informe de descartes se arma sobre el texto crudo.

Conteos clave

Si estos numeros no te dan, algo se desvio antes de que llegues a comparar los archivos.

filas de entrada40
celdas de nota en el archivo120
distribucion_notas.csv30
notas_descartadas.csv9
notas validas contadas111
por motivoausente: 5, fuera_de_rango: 4

Invariantes

Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:

len(distribucion) == 30
distribucion.groupby('nota').size().eq(10).all()
int(distribucion['alumnos'].sum()) == 111
(distribucion['hasta'] - distribucion['desde']).eq(1).all()
len(descartadas) == 9
not descartadas.duplicated(subset=['legajo', 'nota']).any()
set(descartadas['motivo']) <= {'ausente', 'fuera_de_rango'}
int(distribucion['alumnos'].sum()) + len(descartadas) == 120
PISTASSi te trabas, abri esto
  • La ultima invariante es la comprobacion que hay que hacer siempre con un histograma: contadas mas descartadas tiene que dar el total de celdas. Si no da, hay observaciones desapareciendo en silencio.
  • pd.cut con right=False da tramos [desde, hasta) y deja el 10 afuera. El ultimo tramo necesita un tratamiento aparte, o bins con include_lowest y right=True y una decision explicita sobre el 0.
  • Contar a mano con una comparacion doble tambien vale y es mas facil de defender: (v >= desde) & (v < hasta), y el ultimo con <=.
  • El motivo de un guion es ausente, no no_numerico. Que no sea un numero es la consecuencia; que no haya dato es el hecho.

Así tienen que quedar

distribucion_notas.csv (objetivo) · 30 filas, se muestran 5
notadesdehastaalumnos
nota_1010
nota_1120
nota_1230
nota_1345
nota_1456
notas_descartadas.csv (objetivo) · 9 filas, se muestran 5
legajonotavalormotivo
L2606nota_3vacioausente
L2609nota_112.5fuera_de_rango
L2613nota_3N/Aausente
L2618nota_3-1.0fuera_de_rango
L2621nota_3-ausente
El valor original hay que leerlo antes de convertir

Después de pd.to_numeric(..., errors="coerce"), un guion, un N/A y un campo vacío son los tres NaN: ya no se distinguen. El informe de descartes tiene que decir qué había escrito, así que se arma sobre el texto crudo, leyendo con dtype=str, keep_default_na=False.

Es la misma idea de la práctica EJ-5.1: hay preguntas que solo se pueden contestar antes de convertir.

Dónde va un 10 exacto

Los tramos son [desde, hasta): el extremo de abajo entra y el de arriba no. Con esa regla, un 10 no cae en ningún tramo, porque el último es [9, 10).

El contrato lo resuelve haciendo que el último incluya los dos extremos. No es la única salida posible (también se podría poner un tramo de 10 a 11), y es la que produce diez tramos parejos. Lo importante es que en estos datos no hay ningún 10, así que la decisión no cambia una sola celda del resultado, y hay que tomarla igual: el día que aparezca un 10 no va a haber nadie mirando.