Indice / Practicas / EJ-4.4
EJ-4.4 · Ordenar con desempate y nulos al final
Las mismas 50 filas, en otro orden. No se descarta ni se corrige nada: todo el ejercicio es declarar el orden de forma que dos personas distintas obtengan exactamente el mismo archivo.
Qué hay que hacer
A partir de libros_catalogo.csv, producir
libros_ordenados.csv: las 50 filas ordenadas por
año descendente, y dentro de cada año por precio
descendente, con los ausentes al final.
ELI5Explicado facil
Ordenar los libros de una biblioteca del más nuevo al más viejo, y los del mismo año del más caro al más barato.
¿Y si dos libros son del mismo año y salen lo mismo? Ahí hay que tener una tercera regla. Y una cuarta, por si la tercera tampoco alcanza. Se sigue agregando reglas hasta que sea imposible que dos libros empaten, porque si empatan, mañana la lista sale distinta.
Archivos
- Entrada ·
libros_catalogo.csv - Objetivo ·
libros_ordenados.csv - Herramienta ·
comparar.py
Por qué hacen falta cuatro criterios
| # | Criterio | Por qué no alcanza |
|---|---|---|
| 1 | anio DESC | 16 años se repiten en el catálogo |
| 2 | precio DESC | puede empatar, y además hay 2 ausentes |
| 3 | isbn ASC | parece único y no lo es: hay uno repetido |
| 4 | fila_origen ASC | ahora sí: es única por construcción |
El punto 3 es el que hay que ver venir. Que una columna se llame «clave» o «ISBN»
no la hace única: eso se comprueba con is_unique, y en este archivo da
False.
Cómo saber si te salió
python comparar.py mi_salida.csv libros_ordenados.csv
Y hay una comprobación que podés hacer solo, sin el objetivo: ordená dos veces, una
con kind="stable" y otra con kind="quicksort", y compará las
dos listas de fila_origen. Si dan iguales, tu orden es
total. Si dan distintas, te falta un criterio.
Antes de arrancar, mirá los datos
| isbn | titulo | autor | anio | precio |
|---|---|---|---|---|
| 978-1000-001 | Algoritmos vol. 1 | Ximena Molina | 2003 | 57.24 |
| 978-8695-002 | Bases de datos vol. 1 | Guadalupe Gutiérrez | 2016 | 73.18 |
| 978-7073-003 | Redes vol. 1 | Nahuel Vega | 2007 | 47.34 |
| 978-7146-004 | Sistemas operativos vol. 1 | Olivia Ríos | 2025 | 36.31 |
| 978-3259-005 | Compiladores vol. 1 | Delfina Molina | 2006 | 81.58 |
El contrato de salida
libros_ordenados.csv · 50 filas
| Columna | Tipo | Que lleva |
|---|---|---|
fila_origen | entero | Posicion en el archivo de entrada, empezando en 0. Hay que crearla |
isbn | texto | Tal cual viene |
titulo | texto | Tal cual viene |
autor | texto | Tal cual viene. Puede quedar vacio |
anio | entero | Tal cual viene. Puede quedar vacio, y hay un 2199 |
precio | decimal | Tal cual viene, redondeado a 2 decimales. Puede quedar vacio, y hay un -5.0 |
Que hacer con cada defecto
| Defecto | Donde | Accion | Adonde va |
|---|---|---|---|
| anio ausente | 1 fila | NO NO se corrige. Con na_position='last' esa fila queda ULTIMA, porque el primer criterio del orden es el anio | libros_ordenados.csv |
| precio ausente (vacio y token NaN) | 2 filas | NO NO se corrige. Van al final dentro de su grupo de anio | libros_ordenados.csv |
| anio 2199 y precio -5.0, que son imposibles | 2 filas | NO NO se validan: son numeros y ordenan como cualquier otro. El 2199 queda primero de todo | libros_ordenados.csv |
| el isbn 978-1000-001 se repite | 2 filas | NO NO se deduplica. Pero obliga a agregar fila_origen: sin ella esas dos filas empatan en los tres criterios y el orden deja de ser total | libros_ordenados.csv |
Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:
- agregar fila_origen antes de ordenar
- ordenar por anio DESC
- dentro del mismo anio, por precio DESC
- si tambien empata el precio, por isbn ASC
- y si hasta el isbn empata, por fila_origen ASC
Cada criterio desempata al anterior. El ultimo tiene que ser una columna unica o el orden no es total: aca el isbn no alcanza porque se repite, y por eso hace falta fila_origen. na_position='last' vale para todos los criterios a la vez.
Conteos clave
| filas de entrada | 50 |
|---|---|
| libros_ordenados.csv | 50 |
| anios ausentes | 1 |
| precios ausentes | 2 |
| anios que se repiten | 16 |
| isbn repetidos | 1 |
| primera fila (anio mas alto) | 2199 |
| por motivo |
Invariantes
Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:
len(ordenado) == 50
ordenado['fila_origen'].is_unique
sorted(ordenado['fila_origen']) == list(range(50))
ordenado['anio'].dropna().is_monotonic_decreasing
ordenado['anio'].iloc[0] == 2199
ordenado['anio'].isna().iloc[-1]
int(ordenado['precio'].isna().sum()) == 2
set(ordenado['isbn']) == set(pd.read_csv('libros_catalogo.csv')['isbn'])
PISTASSi te trabas, abri esto
- El orden no descarta nada: la salida tiene las mismas 50 filas que la entrada, en otro orden.
- na_position='last' es el default, pero escribilo igual: quien lea el codigo dentro de seis meses no tiene por que acordarse del default.
- El isbn se repite una vez. Si tu orden termina ahi, esas dos filas quedan en el orden que decida el algoritmo, y dos corridas pueden dar archivos distintos.
- Comprobalo vos mismo: ordena dos veces, una con kind='stable' y otra con kind='quicksort', y compara las listas. Si son iguales, el orden es total.
Así tiene que quedar
| fila_origen | isbn | titulo | autor | anio | precio |
|---|---|---|---|---|---|
| 19 | 978-3226-020 | Criptografía vol. 2 | Gabriela Luna | 2199 | 51.72 |
| 46 | 978-6715-047 | Álgebra lineal vol. 5 | Hugo Ángel | 2026 | 44.52 |
| 10 | 978-5379-011 | Algoritmos vol. 2 | Marta Quiroga | 2026 | 42.76 |
| 9 | 978-4347-010 | Criptografía vol. 1 | Zacarías Castro | 2025 | 83.06 |
| 30 | 978-9672-031 | Algoritmos vol. 4 | Belén Sol | 2025 | 58.18 |
Es un año imposible y encabeza la lista, porque el orden no valida: ordena. Lo
mismo con el precio de -5.0, que queda último de su año.
Ver los valores imposibles en los bordes de un orden es, de hecho, una forma
barata de encontrarlos - es lo que hace el paso 2 de la animación de la lección
0.2. Corregirlos es EJ-5.6.
na_position="last" es el default y no se invierte con
ascending=False. La fila sin año queda última de todo el archivo,
no primera.
Escribilo explícitamente aunque sea el default: quien lea el código dentro de seis
meses no tiene por qué acordarse, y en un
sort_values(...).drop_duplicates(keep="last") ese detalle decide qué fila
sobrevive.