Saltar al contenido

Indice / Practicas / EJ-4.2

EJ-4.2 · Top 20 de marzo con columna derivada

Las 20 ventas más grandes de marzo. El importe no está en el archivo: hay que calcularlo. Y hay una venta de marzo que se va a quedar afuera, a propósito.

Qué hay que hacer

A partir de ventas_mensuales.csv, producir ventas_marzo_top20.csv: las 20 ventas de marzo con mayor importe, donde importe = unidades × precio_unitario.

ELI5Explicado facil

Te dan el cuaderno de ventas del trimestre y te piden las 20 ventas más grandes de marzo. El cuaderno anota cuántas unidades y a qué precio, pero nunca el total: eso lo tenés que hacer vos, venta por venta.

Y hay una anotación de marzo escrita con otra letra, en otro formato. Con la regla que estás usando para reconocer marzo, esa se te escapa.

Archivos

La limitación que el contrato declara

En esta unidad todavía no vimos fechas. Para quedarte con marzo vas a usar lo que sí tenés: el texto de la columna empieza con 2026-03.

Funciona para 59 de las 60 ventas de marzo. La que falta tiene la fecha escrita 15/03/2026, y con esa regla no entra. No es un error tuyo ni un descuido del enunciado: es el límite de la herramienta, está escrito en el contrato, y es exactamente el problema que resuelve EJ-5.3.

Que el resultado sea reproducible no significa que sea completo. Vale la pena saber la diferencia.

Cómo saber si te salió

python comparar.py mi_salida.csv ventas_marzo_top20.csv

Antes de arrancar, mirá los datos

ventas_mensuales.csv (entrada) · 180 filas, se muestran 5
fechavendedorproductounidadesprecio_unitario
2026-03-02Carlos RuizAuriculares157.24
2026-03-26Carlos RuizAuriculares557.73
2026-03-31Beatriz MolinaAuriculares159.37
2026-02-09Lucía VegaWebcam645.42
2026-03-27Carlos RuizLaptop7914.44

El contrato de salida

ventas_marzo_top20.csv · 20 filas

ColumnaTipoQue lleva
fila_origenenteroPosicion de la fila en el archivo de entrada, empezando en 0. Hay que crearla
fechatextoLa fecha tal cual viene
vendedortextoTal cual viene
productotextoTal cual viene
unidadesenteroTal cual viene
precio_unitariodecimalTal cual viene
importedecimalunidades por precio_unitario, redondeado a 2 decimales

Orden de las filas: importe DESCENDENTE y, si empatan, fila_origen ASCENDENTE. Los importes ausentes van al final, asi que nunca entran al top. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
la fecha 15/03/2026, que es de marzo pero esta escrita en otro formato1 fila, la 120NO NO entra. Marzo se identifica por el prefijo '2026-03' del texto, que es la herramienta de esta unidadqueda fuera de ventas_marzo_top20.csv, y es una limitacion conocida que resuelve EJ-5.3
unidades o precio ausentes1 fila de marzoel el importe queda ausente y la fila va al final del orden: no llega al top 20queda fuera de ventas_marzo_top20.csv
unidades negativas2 filas, ninguna de marzoNO NO se validan en este ejerciciono afecta a la salida
empates de importe en el borde del top 20no ocurre en este archivo, pero la regla va igualdesempatar desempatar por fila_origen ascendenteventas_marzo_top20.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 filtrar nada
  2. filtrar las fechas que empiezan con 2026-03
  3. calcular importe y redondearlo
  4. ordenar por importe descendente y fila_origen ascendente
  5. quedarse con las primeras 20

fila_origen se agrega ANTES de filtrar: si se agregara despues seria la posicion dentro de marzo y no dentro del archivo, y dejaria de servir para volver a la fila original. Y el redondeo va antes de ordenar, porque dos importes que difieren en el sexto decimal ordenan distinto pero se escriben iguales.

Conteos clave

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

filas de entrada180
ventas de marzo por prefijo59
de esas, con importe calculable58
ventas_marzo_top20.csv20
importe mas alto9885.7
importe mas bajo del top894.0
ventas de marzo que quedan fuera del top39
por motivo

Invariantes

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

len(top) == 20
top['fila_origen'].is_unique
top['fecha'].str.startswith('2026-03').all()
top['importe'].is_monotonic_decreasing
top['importe'].notna().all()
(top['importe'] - (top['unidades'] * top['precio_unitario'])).abs().max() < 0.005
list(top.columns) == ['fila_origen', 'fecha', 'vendedor', 'producto', 'unidades', 'precio_unitario', 'importe']
PISTASSi te trabas, abri esto
  • str.startswith necesita na=False si la columna tiene ausentes, y esta los tiene: hay 4 fechas vacias.
  • assign con lambda te deja calcular el importe y seguir encadenando sin variables intermedias.
  • head(20) despues de ordenar hace lo mismo que nlargest, pero nlargest no te deja declarar el desempate.
  • fila_origen no viene en el archivo. Sin ella no hay ninguna columna unica, y el top 20 dependeria del algoritmo de ordenamiento el dia que dos importes empaten.

Así tiene que quedar

ventas_marzo_top20.csv (objetivo) · 20 filas, se muestran 5
fila_origenfechavendedorproductounidadesprecio_unitarioimporte
602026-03-13Martín RíosLaptop11898.79885.7
1132026-03-16Ana PérezLaptop10910.019100.1
292026-03-30Martín RíosLaptop10887.098870.9
42026-03-27Carlos RuizLaptop7914.446401.08
262026-03-19Diego SolLaptop4942.623770.48
Dos órdenes que cambian el archivo

Uno. fila_origen se agrega antes de filtrar. Si la agregás después, numera las filas de marzo y no las del archivo, y deja de servir para volver a la fila original.

Dos. El importe se redondea antes de ordenar. Dos importes que difieren en el sexto decimal ordenan distinto y se escriben iguales: el archivo sale con dos filas en un orden que nadie puede explicar mirándolo.

Por qué fila_origen y no nlargest

nlargest(20, "importe") hace el trabajo en una línea, y no te deja declarar qué pasa si el puesto 20 y el 21 empatan. En este archivo no empatan; en el del mes que viene, quién sabe.

sort_values([...]).head(20) es una línea más y deja la regla escrita. Ese es el criterio de todo el curso.