Saltar al contenido

Indice / Practicas / EJ-1.3

EJ-1.3 · Promedios descartando notas invalidas

Practica de: 1.5 Las cuatro capas de errorDificultad: B

Cuarenta estudiantes, tres notas cada uno, y nueve filas que hay que dejar afuera. La mitad del ejercicio es calcular el promedio; la otra mitad es decidir a quién no calculárselo.

Qué hay que hacer

A partir de estudiantes_notas.csv (40 filas), producir promedios_descarte.csv con una fila por estudiante que tenga las tres notas usables: el legajo, el nombre, las tres notas y el promedio con dos decimales.

La política es descartar: si una sola de las tres notas no sirve, el estudiante no aparece. Sin pandas.

ELI5Explicado facil

Un promedio de dos notas y uno de tres no son el mismo número, aunque los dos se llamen «promedio». Compararlos es como comparar el promedio de goles de un jugador que jugó todo el año con el de otro que jugó tres partidos.

Este ejercicio elige la respuesta conservadora: si no están las tres, no hay promedio.

Archivos

El par con EJ-5.7

Mismo archivo, política opuesta, resultado distinto

El ejercicio EJ-5.7 de la unidad 5 usa este mismo archivo y en vez de descartar, imputa las notas que faltan. Su objetivo tiene 40 filas; este tiene 31.

Ninguno de los dos está mal. La política la fija el enunciado, no los datos, y esa es la idea que ninguna otra sección del curso enseña.

Los tres defectos, en orden de peligro

CuántosQuéCómo se detecta
4 celdasLos tokens '', 'N/A' y '-' (dos veces)float() falla: un except ValueError alcanza
1 celdaEl token 'NaN'Nadie. float("NaN") devuelve un número y el promedio da nan
4 celdasNotas fuera de 0 a 10, incluida una de -1Nadie. Son números perfectamente válidos… para Python

Nueve celdas defectuosas, nueve estudiantes descartados: cada uno tiene un solo problema. Si te dan 5 descartados te faltó el chequeo de rango; si te dan 4, te faltó el de ausentes.

Cómo saber si te salió

python comparar.py mi_salida.csv promedios_descarte.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

promedios_descarte.csv · 31 filas

ColumnaTipoQue lleva
legajotextoEl legajo tal cual vino
estudiantetextoEl nombre tal cual vino
nota_1decimalLa nota como numero, 2 decimales
nota_2decimalLa nota como numero, 2 decimales
nota_3decimalLa nota como numero, 2 decimales
promediodecimal(nota_1 + nota_2 + nota_3) / 3, redondeado a 2 decimales

Orden de las filas: legajo ascendente. Los 40 legajos del archivo son distintos, asi que el orden es total y no hace falta desempate. Indice: no se escribe: csv.DictWriter no agrega ninguna columna de indice, y con pandas seria to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
nota ausente5 celdas, todas en nota_3: los tokens '', 'N/A', '-' (x2) y 'NaN'descartar descartar al estudiante entero, no solo la notano aparece en promedios_descarte.csv
el token 'NaN' en nota_31 celdatratarlo tratarlo como ausente. Es el caso peligroso: float('NaN') NO falla, devuelve nan, y un solo nan convierte el promedio entero en nanno aparece en promedios_descarte.csv
nota fuera del rango 0 a 104 celdas: 2 en nota_1, 1 en nota_2 y 1 en nota_3, incluida una nota de -1descartar descartar al estudiante entero. El rango lo fija el reglamento de la materia, no los datosno aparece en promedios_descarte.csv
nota no numerica0 celdas en este archivola la comprobacion va igual: los cuatro tokens de ausente ya la cubren, pero un 'ocho' escrito con letras entraria por acano aparece en promedios_descarte.csv
Orden de comprobacion

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

  1. para cada una de las tres notas: token de ausente, conversion a float, rango 0 a 10
  2. si alguna de las tres falla, el estudiante no participa
  3. recien con las tres notas usables se calcula el promedio

El token de ausente se revisa ANTES de convertir, porque float('NaN') no falla: si se convierte primero, ese estudiante entra con un nan y arruina su promedio sin levantar ninguna excepcion.

Conteos clave

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

filas de entrada40
promedios_descarte.csv31
estudiantes descartados9
por motivoausente: 5, fuera_de_rango: 4

Invariantes

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

len(promedios) == 31
promedios['legajo'].is_unique
promedios['legajo'].is_monotonic_increasing
not promedios.isna().any().any()
promedios[['nota_1', 'nota_2', 'nota_3']].ge(0).all().all()
promedios[['nota_1', 'nota_2', 'nota_3']].le(10).all().all()
promedios['promedio'].between(0, 10).all()
(promedios['promedio'] - promedios[['nota_1','nota_2','nota_3']].mean(axis=1)).abs().max() < 0.005
PISTASSi te trabas, abri esto
  • float('NaN') no levanta ValueError: devuelve nan. Si no filtras el token antes de convertir, ese estudiante entra y su promedio da nan.
  • El estudiante se descarta ENTERO, no la nota suelta. Un promedio sobre dos notas no es comparable con uno sobre tres.
  • Los 9 descartados son 5 por nota ausente y 4 por nota fuera de rango. Si te dan 5, te falto el chequeo de rango; si te dan 4, te falto el de ausentes.
  • Compara tu resultado con el de EJ-5.7 cuando llegues: mismo archivo, politica opuesta, y ninguno de los dos esta mal.

Así tiene que quedar

promedios_descarte.csv (objetivo) · 31 filas, se muestran 5
legajoestudiantenota_1nota_2nota_3promedio
L2601Karina Acosta9.74.78.67.67
L2602Santiago Ramos6.03.84.24.67
L2603Carla Luna8.13.63.85.17
L2604Lucas Núñez7.37.43.46.03
L2605Tamara Torres9.59.57.88.93
El orden de las comprobaciones no es indistinto

El token de ausente se revisa antes de convertir. Si convertís primero, float("NaN") no se queja, ese estudiante entra con un nan, y su promedio queda en nan sin que se levante ninguna excepción - ni siquiera se nota hasta que alguien mira el archivo.

Redondeo

round(suma / 3, 2) sobre el número, no al escribir. Las tres notas ya vienen con un decimal y se escriben tal cual; el único cálculo es el promedio.