Saltar al contenido

Indice / Practicas / EJ-4.5

EJ-4.5 · Indice compuesto y clave duplicada

Practica de: 4.6 El indiceDificultad: M

¿Qué identifica una fila de esta tabla? No es el estudiante, y no es el curso. Descubrirlo - y comprobar si los datos lo respetan - es todo el ejercicio.

Qué hay que hacer

A partir de academico_inscripciones.csv, producir dos archivos:

ELI5Explicado facil

Una lista de quién se anotó a qué. Ana aparece tres veces porque se anotó a tres materias, y en Álgebra aparecen veinte personas.

Entonces ni el nombre ni la materia alcanzan para señalar una línea de la lista: hace falta el par. Y aun así hay una línea escrita dos veces, con dos notas distintas, que nadie sabe cuál vale.

Archivos

Las tres preguntas del informe

El informe evalúa tres candidatos a clave. Antes de escribir código, respondelas vos:

  1. ¿estudiante_id identifica una fila? - hay 43 estudiantes y 110 filas.
  2. ¿curso_id? - hay 9 cursos.
  3. ¿El par (estudiante_id, curso_id)? - esta es la interesante, y la respuesta no es un sí limpio.

Los tres dan es_unica = 0. Pero los tres 0 significan cosas muy distintas, y esa es la idea que vale más que el archivo.

Cómo saber si te salió

python comparar.py mi_tabla.csv inscripciones_indexadas.csv
python comparar.py mi_informe.csv clave_duplicada.csv

Antes de arrancar, mirá los datos

academico_inscripciones.csv (entrada) · 110 filas, se muestran 5
estudiante_idcurso_idnota
3555.8
2847.5
2257.5
17611.5
2119.3

El contrato de salida

inscripciones_indexadas.csv · 110 filas

ColumnaTipoQue lleva
estudiante_identeroPrimera parte de la clave
curso_identeroSegunda parte de la clave
fila_origenenteroPosicion en el archivo de entrada, empezando en 0. Hay que crearla
notadecimalTal cual viene, redondeada a 2 decimales. Puede quedar vacia
clave_repetidaentero1 si el par (estudiante_id, curso_id) de esa fila aparece mas de una vez en el archivo; 0 si no

Orden de las filas: estudiante_id ASC, curso_id ASC, fila_origen ASC. El par no es unico, asi que fila_origen es lo que hace total al orden. Indice: no se escribe: to_csv(index=False)

clave_duplicada.csv · 3 filas

ColumnaTipoQue lleva
columnatextoEl candidato a clave: 'curso_id', 'estudiante_id' o 'estudiante_id+curso_id'
es_unicaentero1 si ese candidato identifica cada fila sin repetir; 0 si no
valores_distintosenteroCuantas combinaciones distintas de ese candidato hay
filasenteroSiempre 110: el total del archivo
filas_repetidasenteroCuantas filas participan de una repeticion, contando TODAS las del grupo (duplicated con keep=False)

Orden de las filas: columna ascendente, alfabeticamente. Es unica en este archivo. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
el par (35, 5) aparece dos veces, con notas 5.8 y 6.02 filas: la 0 y la 109NO NO se deduplica ni se descarta. Se MARCA con clave_repetida = 1 y se informa en clave_duplicada.csvlas dos salidas
nota ausente2 filasNO NO se imputa ni se descarta: la nota no forma parte de la claveinscripciones_indexadas.csv, con el campo vacio
estudiante_id se repite en 99 filas43 estudiantes para 110 inscripcionesNO NO es un defecto: una fila es una inscripcion, no un estudiante. El informe lo dice con es_unica = 0clave_duplicada.csv
Orden de comprobacion

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

  1. agregar fila_origen antes de tocar nada
  2. marcar las filas cuyo par de clave se repite, con duplicated(subset=CLAVE, keep=False)
  3. ordenar por estudiante_id, curso_id y fila_origen
  4. armar el informe evaluando los tres candidatos sobre el archivo COMPLETO

El informe se calcula sobre el archivo entero y no sobre la tabla ya ordenada: el orden no cambia los conteos, pero calcularlo antes deja claro que es un diagnostico de la entrada. Y keep=False es lo que hace que se marquen LAS DOS filas del par repetido, no solo la segunda.

Conteos clave

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

filas de entrada110
inscripciones_indexadas.csv110
clave_duplicada.csv3
estudiantes distintos43
cursos distintos9
pares (estudiante, curso) distintos109
filas con clave_repetida = 12
notas ausentes2
por motivo

Invariantes

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

len(tabla) == 110
tabla['fila_origen'].is_unique
int(tabla['clave_repetida'].sum()) == 2
len(informe) == 3
int(informe['es_unica'].sum()) == 0
informe.loc[informe['columna'] == 'estudiante_id+curso_id', 'valores_distintos'].item() == 109
informe.loc[informe['columna'] == 'estudiante_id+curso_id', 'filas_repetidas'].item() == 2
(informe['filas'] == 110).all()
PISTASSi te trabas, abri esto
  • duplicated(keep='first') marca solo la segunda aparicion; duplicated(keep=False) marca las dos. Para una bandera de «esta fila esta en conflicto» hace falta keep=False.
  • Ninguno de los tres candidatos es unico, ni siquiera el par. Eso no significa que la clave este mal elegida: significa que los datos la violan una vez.
  • El orden termina en fila_origen justamente porque el par se repite: sin ese ultimo criterio, esas dos filas quedan en el orden que decida el algoritmo.
  • drop_duplicates(subset=columnas) cuenta combinaciones distintas sin tener que armar una clave de texto a mano.

Así tiene que quedar

inscripciones_indexadas.csv (objetivo) · 110 filas, se muestran 5
estudiante_idcurso_idfila_origennotaclave_repetida
13283.70
1771087.00
2215vacio0
26715.00
28885.30
clave_duplicada.csv (objetivo) · 3 filas, se muestran 3
columnaes_unicavalores_distintosfilasfilas_repetidas
curso_id09110109
estudiante_id04311099
estudiante_id+curso_id01091102
Los tres 0 del informe no dicen lo mismo

estudiante_id se repite porque así es la tabla: un estudiante hace varias materias. Eso no es un defecto, es el grano. La conclusión es «esta columna no es la clave», no «hay que arreglar algo».

El par (estudiante_id, curso_id) se repite porque un dato está mal: alguien cargó dos veces la misma inscripción, con dos notas distintas. Ahí sí hay algo que arreglar, y el enunciado tiene que decidir cuál nota vale.

Confundir los dos casos lleva a deduplicar por estudiante_id y borrar 109 inscripciones legítimas.

keep=False no es un detalle

duplicated() por defecto marca la segunda aparición y deja la primera sin marcar - sirve para contar «cuántas sobran». duplicated(keep=False) marca las dos, que es lo que hace falta para una bandera de «esta fila está en conflicto».

Con el default, la fila 0 saldría con clave_repetida = 0 y quien la lea pensaría que está bien.