Indice / Practicas / EJ-5.7
EJ-5.7 · Imputar notas invalidas con la mediana
Mismo archivo que EJ-1.3, política opuesta. Allá se
descarta lo que no sirve; acá no se pierde ni una fila. Los dos
resultados son correctos, y por eso hay que decir cuál se eligió.
Qué hay que hacer
A partir de estudiantes_notas.csv, producir
notas_imputadas.csv: las 40 filas, con las tres notas
completas y dentro del rango 0 a 10, más el promedio.
Toda nota que falte o que sea imposible se reemplaza por la mediana de su columna. Y queda anotado cuántas notas de cada alumno son inventadas: esa columna es tan importante como las notas.
ELI5Explicado facil
Un profesor pierde algunas notas de su planilla. Tiene dos opciones:
- Sacar a esos alumnos de la lista. La planilla queda impecable y hay alumnos que desaparecieron.
- Ponerles la nota típica del curso y escribir al lado «esta la puse yo». La planilla queda completa, y cualquiera que la lea sabe cuáles son reales.
Este ejercicio hace lo segundo. Lo que no se puede hacer es inventar la nota y no decirlo.
Archivos
- Entrada ·
estudiantes_notas.csv - Objetivo ·
notas_imputadas.csv - Herramienta ·
comparar.py
Ausente y fuera de rango terminan igual, pero no son lo mismo
Una nota vacía y un 99 en una escala de 0 a 10 reciben el mismo tratamiento: los
dos se imputan. Pero llegaron por caminos distintos, y eso importa para el informe:
en un caso nadie cargó el dato, en el otro alguien cargó uno
malo. La columna notas_imputadas los junta a propósito, porque
para quien lee el promedio la pregunta es una sola: ¿cuántas de estas notas son
de verdad?
Cómo saber si te salió
python comparar.py mi_salida.csv notas_imputadas.csv
Antes de arrancar, mirá los datos
| legajo | estudiante | nota_1 | nota_2 | nota_3 |
|---|---|---|---|---|
| L2601 | Karina Acosta | 9.7 | 4.7 | 8.6 |
| L2602 | Santiago Ramos | 6.0 | 3.8 | 4.2 |
| L2603 | Carla Luna | 8.1 | 3.6 | 3.8 |
| L2604 | Lucas Núñez | 7.3 | 7.4 | 3.4 |
| L2605 | Tamara Torres | 9.5 | 9.5 | 7.8 |
Fijate en nota_3: tiene dos guiones sueltos, y con eso alcanza para
que pandas lea la columna entera como texto.
El contrato de salida
notas_imputadas.csv · 40 filas
| Columna | Tipo | Que lleva |
|---|---|---|
legajo | texto | El legajo original, sin tocar |
estudiante | texto | Sin espacios en los extremos |
nota_1 | decimal | Entre 0 y 10, redondeada a 2 decimales |
nota_2 | decimal | Entre 0 y 10, redondeada a 2 decimales |
nota_3 | decimal | Entre 0 y 10, redondeada a 2 decimales |
notas_imputadas | entero | Cuantas de las tres notas de esa fila las pusimos nosotros: 0, 1, 2 o 3 |
promedio | decimal | Media de las tres notas ya imputadas, redondeada a 2 decimales |
Que hacer con cada defecto
| Defecto | Donde | Accion | Adonde va |
|---|---|---|---|
| nota ausente: campo vacio o los tokens NaN, N/A, null y - | 5 celdas de nota_3 | imputar imputar con la mediana de las notas VALIDAS de esa misma columna | notas_imputadas.csv, sumando 1 a notas_imputadas de esa fila |
| nota fuera del rango 0 a 10: 12.5, 10.5 y 99.0 | 2 celdas de nota_1 (L2609, L2634) y 1 de nota_2 (L2626) | tratarla tratarla como si faltara e imputar con la mediana de su columna. NO se recorta con clip: recortar convierte un imposible en un valor creible | notas_imputadas.csv, sumando 1 a notas_imputadas de esa fila |
| nota negativa (-1.0) | 1 celda de nota_3, la de L2618 | es es un caso mas de fuera de rango: se imputa igual | notas_imputadas.csv |
| ninguna fila se descarta | las 40 | esta esta es la politica del ejercicio, y es lo unico que lo diferencia de EJ-1.3 sobre el mismo archivo | notas_imputadas.csv |
Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:
- marcar como invalida toda nota ausente o fuera del rango 0 a 10
- calcular la mediana de cada columna SOLO con sus notas validas
- imputar
- recien despues calcular el promedio de las tres notas
Si la mediana se calcula antes de marcar lo invalido, el 99 de nota_2 la corre para arriba y las imputaciones quedan mal. Y si el promedio se calcula antes de imputar, las filas con una nota faltante promedian dos notas en vez de tres.
Conteos clave
| filas de entrada | 40 |
|---|---|
| notas_imputadas.csv | 40 |
| notas imputadas en total | 9 |
| filas con alguna nota imputada | 9 |
| imputadas en nota_1 | 2 |
| imputadas en nota_2 | 1 |
| imputadas en nota_3 | 6 |
| mediana de nota_1 | 6.05 |
| mediana de nota_2 | 5.4 |
| mediana de nota_3 | 6.05 |
| por motivo |
Invariantes
Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:
len(salida) == 40
salida['legajo'].is_unique
salida[['nota_1', 'nota_2', 'nota_3']].notna().all().all()
salida[['nota_1', 'nota_2', 'nota_3']].ge(0).all().all()
salida[['nota_1', 'nota_2', 'nota_3']].le(10).all().all()
int(salida['notas_imputadas'].sum()) == 9
salida['notas_imputadas'].between(0, 3).all()
(salida['promedio'] - salida[['nota_1','nota_2','nota_3']].mean(axis=1)).abs().max() < 0.005
PISTASSi te trabas, abri esto
- La mediana de una columna se calcula con las notas validas de ESA columna, no con las tres juntas.
- clip(0, 10) parece la solucion elegante y es la trampa: un 99 recortado a 10 queda indistinguible de un 10 real, para siempre.
- Redondear la mediana a 2 decimales antes de imputar evita que el archivo tenga un valor con 15 decimales escondido.
- notas_imputadas cuenta por fila, no por columna: es la suma de las tres banderas.
- Compara tu resultado con EJ-1.3, que resuelve el mismo archivo descartando. Ninguno de los dos es el correcto: son dos politicas, y el enunciado es el que elige.
Así tiene que quedar
| legajo | estudiante | nota_1 | nota_2 | nota_3 | notas_imputadas | promedio |
|---|---|---|---|---|---|---|
| L2601 | Karina Acosta | 9.7 | 4.7 | 8.6 | 0 | 7.67 |
| L2602 | Santiago Ramos | 6.0 | 3.8 | 4.2 | 0 | 4.67 |
| L2603 | Carla Luna | 8.1 | 3.6 | 3.8 | 0 | 5.17 |
| L2604 | Lucas Núñez | 7.3 | 7.4 | 3.4 | 0 | 6.03 |
| L2605 | Tamara Torres | 9.5 | 9.5 | 7.8 | 0 | 8.93 |
clip(0, 10) es la solución elegante y equivocada
Recortar deja todo dentro del rango en una línea, sin perder ninguna fila y sin tener que calcular ninguna mediana. El problema es que un 99 recortado a 10 es indistinguible de un 10 real, para siempre, y ese alumno pasa a ser el mejor del curso por un error de tipeo.
Imputar con la mediana también inventa un número - pero lo deja marcado en
notas_imputadas, y ahí está toda la diferencia.
Uno. La mediana se calcula después de marcar lo inválido.
Si el 99 entra en el cálculo, la mediana de nota_2 se corre para arriba
y las imputaciones quedan mal.
Dos. El promedio se calcula después de imputar. Si se calcula antes, las filas con una nota faltante promedian dos notas en vez de tres, y salen infladas sin que nada avise.