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:
transacciones_normalizadas.csv- las operaciones utilizables, contipoycategoriadentro de su dominio.transacciones_rechazadas.csv- una fila por operación descartada, con la columna, el valor original y el motivo.
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
- Entrada ·
transacciones_categorias.csv - Objetivo ·
transacciones_normalizadas.csv - Objetivo ·
transacciones_rechazadas.csv - Herramienta ·
comparar.py
El orden que decide el resultado
Este ejercicio tiene una sola trampa, y es de orden de operaciones:
- Si normalizás primero y validás después, hay 1 valor fuera del dominio.
- 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
| id | fecha | categoria | tipo | importe |
|---|---|---|---|---|
| OP0001 | 2026-03-16 | Infraestructura | ingreso | 380.76 |
| OP0002 | 2026-04-27 | Consultoría | ingreso | 794.05 |
| OP0003 | 2026-06-25 | Infraestructura | gasto | 2865.71 |
| OP0004 | 2026-05-31 | Hardware | gasto | 3407.7 |
| OP0005 | 2026-04-21 | Hardware | gasto | 1256.83 |
El contrato de salida
transacciones_normalizadas.csv · 141 filas
| Columna | Tipo | Que lleva |
|---|---|---|
id | texto | El id original, sin tocar |
fecha | texto | La fecha tal cual, sin espacios en los extremos. Todas son validas en este archivo |
categoria | texto | Una de las 7 categorias permitidas, sin espacios en los extremos |
tipo | texto | ingreso o gasto, en minusculas |
importe | decimal | El importe en pesos, positivo, redondeado a 2 decimales |
transacciones_rechazadas.csv · 9 filas
| Columna | Tipo | Que lleva |
|---|---|---|
id_origen | texto | El id de la transaccion descartada |
columna | texto | En que columna estaba el problema |
valor_original | texto | El valor tal cual venia en el archivo |
motivo | texto | Uno del vocabulario cerrado del curso |
Que hacer con cada defecto
| Defecto | Donde | Accion | Adonde va |
|---|---|---|---|
| tipo escrito INGRESO en mayusculas | 1 fila, OP0096 | normalizar normalizar con .str.lower(). NO es un valor desconocido: es el mismo escrito distinto | transacciones_normalizadas.csv, con tipo ingreso |
| tipo devolucion, que no esta en el dominio | 1 fila, OP0118 | descartar descartar | transacciones_rechazadas.csv con motivo dominio_desconocido |
| categoria vacia | 1 fila, OP0073 | descartar descartar | transacciones_rechazadas.csv con motivo ausente |
| importe ausente: campo vacio o los tokens N/A, null y - | 6 filas: OP0025, OP0050, OP0075, OP0100, OP0125 y OP0150 | descartar descartar | transacciones_rechazadas.csv con motivo ausente |
| importe negativo (-310.0) en una operacion de tipo gasto | 1 fila, OP0041 | descartar. descartar. El signo lo lleva la columna tipo, no el importe: un importe negativo contradice el diseno de la tabla | transacciones_rechazadas.csv con motivo negativo_incoherente |
| importe de 5.000.000, mucho mayor que el resto | 1 fila | NO NO se juzga en este ejercicio: pasa tal cual | transacciones_normalizadas.csv |
Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:
- tipo fuera del dominio (despues de normalizar)
- categoria vacia
- categoria fuera del dominio
- importe ausente
- 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
| filas de entrada | 150 |
|---|---|
| transacciones_normalizadas.csv | 141 |
| transacciones_rechazadas.csv | 9 |
| tipos normalizados de mayusculas a minusculas | 1 |
| ingreso en la salida | 62 |
| gasto en la salida | 79 |
| por motivo | ausente: 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
| id | fecha | categoria | tipo | importe |
|---|---|---|---|---|
| OP0001 | 2026-03-16 | Infraestructura | ingreso | 380.76 |
| OP0002 | 2026-04-27 | Consultoría | ingreso | 794.05 |
| OP0003 | 2026-06-25 | Infraestructura | gasto | 2865.71 |
| OP0004 | 2026-05-31 | Hardware | gasto | 3407.7 |
| OP0005 | 2026-04-21 | Hardware | gasto | 1256.83 |
| id_origen | columna | valor_original | motivo |
|---|---|---|---|
| OP0025 | importe | N/A | ausente |
| OP0041 | importe | -310.0 | negativo_incoherente |
| OP0050 | importe | vacio | ausente |
| OP0073 | categoria | vacio | ausente |
| OP0075 | importe | - | ausente |
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.
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.