Saltar al contenido

Indice / Practicas / EJ-5.4

EJ-5.4 · Normalizar un dominio cerrado

Dos columnas de este archivo solo admiten valores de una lista cerrada. Una fila tiene el valor correcto escrito en mayúsculas y otra tiene un valor que no existe: parecen el mismo problema y no lo son.

Qué hay que hacer

A partir de transacciones_categorias.csv, producir:

ELI5Explicado facil

Un formulario de la escuela admite dos respuestas: sí o no. Alguien escribió SÍ en mayúsculas y otro escribió quizás.

El primero contestó bien, solo que gritando: se arregla poniéndolo en minúsculas. El segundo contestó algo que el formulario no acepta y hay que apartarlo. Tratar a los dos igual es tirar una respuesta buena.

Archivos

El orden que decide el resultado

Este ejercicio tiene una sola trampa, y es de orden de operaciones:

  1. Si normalizás primero y validás después, hay 1 valor fuera del dominio.
  2. Si validás primero, hay 2: se pierde una fila buena y el informe miente sobre cuántos problemas distintos había.

Los dos programas corren sin error. Solo uno produce el archivo del contrato.

Cómo saber si te salió

python comparar.py mi_normalizadas.csv transacciones_normalizadas.csv
python comparar.py mi_rechazadas.csv transacciones_rechazadas.csv

Antes de arrancar, mirá los datos

transacciones_categorias.csv (entrada) · 150 filas, se muestran 5
idfechacategoriatipoimporte
OP00012026-03-16Infraestructuraingreso380.76
OP00022026-04-27Consultoríaingreso794.05
OP00032026-06-25Infraestructuragasto2865.71
OP00042026-05-31Hardwaregasto3407.7
OP00052026-04-21Hardwaregasto1256.83

El contrato de salida

transacciones_normalizadas.csv · 141 filas

ColumnaTipoQue lleva
idtextoEl id original, sin tocar
fechatextoLa fecha tal cual, sin espacios en los extremos. Todas son validas en este archivo
categoriatextoUna de las 7 categorias permitidas, sin espacios en los extremos
tipotextoingreso o gasto, en minusculas
importedecimalEl importe en pesos, positivo, redondeado a 2 decimales

Orden de las filas: id ascendente. Es unico, asi que no hace falta desempate. Indice: no se escribe: to_csv(index=False)

transacciones_rechazadas.csv · 9 filas

ColumnaTipoQue lleva
id_origentextoEl id de la transaccion descartada
columnatextoEn que columna estaba el problema
valor_originaltextoEl valor tal cual venia en el archivo
motivotextoUno del vocabulario cerrado del curso

Orden de las filas: id_origen ascendente. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
tipo escrito INGRESO en mayusculas1 fila, OP0096normalizar normalizar con .str.lower(). NO es un valor desconocido: es el mismo escrito distintotransacciones_normalizadas.csv, con tipo ingreso
tipo devolucion, que no esta en el dominio1 fila, OP0118descartar descartartransacciones_rechazadas.csv con motivo dominio_desconocido
categoria vacia1 fila, OP0073descartar descartartransacciones_rechazadas.csv con motivo ausente
importe ausente: campo vacio o los tokens N/A, null y -6 filas: OP0025, OP0050, OP0075, OP0100, OP0125 y OP0150descartar descartartransacciones_rechazadas.csv con motivo ausente
importe negativo (-310.0) en una operacion de tipo gasto1 fila, OP0041descartar. descartar. El signo lo lleva la columna tipo, no el importe: un importe negativo contradice el diseno de la tablatransacciones_rechazadas.csv con motivo negativo_incoherente
importe de 5.000.000, mucho mayor que el resto1 filaNO NO se juzga en este ejercicio: pasa tal cualtransacciones_normalizadas.csv
Orden de comprobacion

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

  1. tipo fuera del dominio (despues de normalizar)
  2. categoria vacia
  3. categoria fuera del dominio
  4. importe ausente
  5. importe negativo

Una fila puede fallar por mas de una cosa y se informa SOLO la primera de esta lista, para que cada rechazo aparezca una vez y valga normalizadas + rechazadas = 150. Y la normalizacion va antes que toda la lista: validar primero convertiria INGRESO en un rechazo que no corresponde.

Conteos clave

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

filas de entrada150
transacciones_normalizadas.csv141
transacciones_rechazadas.csv9
tipos normalizados de mayusculas a minusculas1
ingreso en la salida62
gasto en la salida79
por motivoausente: 7, dominio_desconocido: 1, negativo_incoherente: 1

Invariantes

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

len(normalizadas) + len(rechazadas) == 150
normalizadas['id'].is_unique
set(normalizadas['tipo']) == {'ingreso', 'gasto'}
normalizadas['categoria'].isin(CATEGORIAS).all()
(normalizadas['importe'] > 0).all()
normalizadas.notna().all().all()
rechazadas['id_origen'].is_unique
set(rechazadas['motivo']) <= {'ausente', 'dominio_desconocido', 'negativo_incoherente'}
PISTASSi te trabas, abri esto
  • Normalizar y despues validar. Al reves se rechaza una fila buena y se informa un problema que no existe.
  • isin compara exacto: 'INGRESO' no es 'ingreso'. Ese es todo el punto del ejercicio.
  • El guion no es un token de ausente por defecto. Si no lo declaras, esa fila no se rechaza por ausente sino que rompe la conversion a numero.
  • Una categoria vacia y una categoria desconocida son dos motivos distintos, aunque las dos terminen descartadas.

Así tiene que quedar

transacciones_normalizadas.csv (objetivo) · 141 filas, se muestran 5
idfechacategoriatipoimporte
OP00012026-03-16Infraestructuraingreso380.76
OP00022026-04-27Consultoríaingreso794.05
OP00032026-06-25Infraestructuragasto2865.71
OP00042026-05-31Hardwaregasto3407.7
OP00052026-04-21Hardwaregasto1256.83
transacciones_rechazadas.csv (objetivo) · 9 filas, se muestran 5
id_origencolumnavalor_originalmotivo
OP0025importeN/Aausente
OP0041importe-310.0negativo_incoherente
OP0050importevacioausente
OP0073categoriavacioausente
OP0075importe-ausente
Un importe negativo no es un importe chico

La fila OP0041 tiene -310.0 en una operación de tipo gasto. En esta tabla el signo lo lleva la columna tipo, no el importe: un gasto ya es negativo por ser gasto. Que además el número venga con signo significa que alguien cargó dos veces la misma idea, y no hay forma de saber cuál de las dos vale.

Por eso el motivo es negativo_incoherente y no fuera_de_rango: el problema no es el valor, es que contradice a otra columna.

Lo que este ejercicio no hace

Hay una operación de 5.000.000 cuando el resto ronda los mil. Pasa igual, y está declarado en el contrato. Decidir qué hacer con un valor raro pero posible es otra discusión - la de la lección 5.6 - y mezclarla acá haría que dos personas con criterios distintos entreguen archivos distintos.