Curso de Python / Limpiar y analizar tablas con pandas

pandas representa datos tabulares mediante un DataFrame. Para obtener totales interpretables, separa lectura, validación, agrupación y guardado, y comunica cuántas filas se rechazaron en vez de hacer desaparecer sus problemas durante la limpieza.

Elegir tipos antes de agrupar

Un DataFrame es una estructura parecida a una tabla y una Series representa una columna. La inferencia de tipos al leer CSV puede diferir del contrato de la aplicación. Si un identificador contiene ceros iniciales, leerlo como número puede perder información; consérvalo como texto y convierte explícitamente las columnas numéricas.

Instala pandas en el entorno virtual del proyecto:

python -m pip install pandas

Es un paquete externo. Elige una versión compatible con tu intérprete y sistema, y conserva las dependencias del proyecto. La introducción oficial a pandas explica sus estructuras y operaciones básicas.

Ejecutar una validación y un resumen completos

Guarda este código como pandas_demo.py y ejecuta python pandas_demo.py. La entrada está incluida en el programa para reproducir el mismo resultado sin archivos adicionales.

from io import StringIO
import pandas as pd

raw = "id,category,amount\ne1,food,3500\ne2,food,8000\ne3,transport,2500\ne4,food,bad\n"
df = pd.read_csv(StringIO(raw), dtype="string", keep_default_na=False)
amounts = pd.to_numeric(df["amount"], errors="coerce")
valid = amounts.notna() & (amounts >= 0) & (amounts % 1 == 0)
clean = df.loc[valid].copy()
clean["amount"] = amounts.loc[valid].astype("int64")
report = clean.groupby("category", as_index=False, sort=True)["amount"].sum()
print("accepted:", len(clean), "rejected:", int((~valid).sum()))
for row in report.itertuples(index=False):
    print(row.category, row.amount)
accepted: 3 rejected: 1
food 11500
transport 2500

Se aceptan tres gastos y se rechaza el texto bad. La comida suma 11500 y el transporte 2500. Esos valores describen las filas aceptadas; el resultado no demuestra que toda la entrada fuese correcta.

Interpretar conversiones, máscaras y copias

errors="coerce" marca las conversiones fallidas como valores ausentes. La máscara valid selecciona importes presentes, no negativos y sin parte fraccionaria. loc selecciona las filas y copy crea la tabla sobre la que se asigna la columna convertida. La referencia de to_numeric detalla la conversión y sus límites de precisión.

Los pequeños importes del ejercicio caben en int64. Enteros muy grandes o dinero decimal exacto necesitan otra política de precisión y rango. Esta máscara tampoco valida categorías vacías ni identificadores duplicados: añade esas reglas si forman parte del contrato. Reemplazar importes ausentes por cero borraría la diferencia entre un dato desconocido y un cero real.

Para leer un archivo real, sustituye la creación de la tabla por pd.read_csv("expenses-input.csv", dtype={"id":"string", "category":"string", "amount":"string"}) y aplica después la conversión. Conserva las filas rechazadas por separado. La política de valores ausentes de esa lectura debe coincidir con tus datos.

Guardar y reconciliar el resultado

Añade esta línea al final del mismo archivo, después de crear report:

report.to_csv("category-report.csv", index=False, encoding="utf-8")

index=False evita guardar el índice de la tabla. Elige una ruta nueva: to_csv reemplaza un archivo existente con ese nombre. Comprueba que la suma aceptada y la del informe sean ambas 14000.

  1. Sustituye bad por cero y compara los recuentos.
  2. Prueba menos uno y confirma el rechazo.
  3. Restaura la entrada y reconcilia aceptados más rechazados con todas las filas.

El proyecto CSV con la biblioteca estándar ofrece una alternativa explícita fila por fila cuando no necesitas pandas.