Python Reto #15 — Leer un CSV y calcular métricas (sin pandas)

Nivel: Intermedio
Tema: Archivos, CSV, parsing, conversión de tipos, agregaciones, validación de entradas, tests con pytest
Objetivo: Leer un archivo CSV usando solo la librería estándar y calcular métricas básicas (conteo, suma y promedio) de una columna numérica, ignorando filas inválidas.

Enunciado

Crea una función llamada metricas_csv(ruta_csv, columna) que:

  1. Reciba:
    • ruta_csv: ruta (string) a un archivo CSV con cabecera
    • columna: nombre (string) de una columna numérica
  2. Si ruta_csv es None o columna es None, lance TypeError.
  3. Si ruta_csv o columna no son str, lance TypeError.
  4. Si el archivo no existe, lance FileNotFoundError.
  5. Lea el CSV y calcule métricas para la columna indicada:
    • count: número de filas válidas (con valor numérico convertible)
    • sum: suma de los valores válidos
    • avg: promedio (si count es 0, avg debe ser 0)
  6. Debe ignorar filas donde:
    • falte la columna,
    • el valor esté vacío,
    • el valor no se pueda convertir a float.

Debe devolver un diccionario con esta forma:

{"count": int, "sum": float, "avg": float}

CSV de ejemplo

ventas.csv

producto,importe
A,10
B,20.5
C,abc
D,
E,5

metricas_csv("ventas.csv", "importe") debería devolver:

{"count": 3, "sum": 35.5, "avg": 11.833333333333334}

Pistas

  1. Usa csv.DictReader para leer filas como diccionarios.
  2. Convierte a número con float(valor).
  3. Maneja conversiones fallidas con try/except ValueError.
  4. Asegura casos borde: archivo vacío, columna inexistente, count == 0.

Solución explicada (paso a paso)

  1. Validamos tipos (ruta_csv y columna deben ser str).
  2. Abrimos el archivo en modo texto con newline="".
  3. Usamos csv.DictReader para obtener cada fila como diccionario.
  4. Para cada fila:
    • obtenemos el valor de la columna,
    • verificamos que exista y no esté vacío,
    • intentamos convertirlo a float,
    • si se puede, lo acumulamos en suma y aumentamos count.
  5. Calculamos promedio:
    • si count es 0 → avg = 0
    • si no → avg = total / count
  6. Devolvemos el diccionario con métricas.

Ejecuta:

  • pytest -q

Variantes para subir de nivel (opcional)

  1. Devolver también min/max de la columna
  2. Permitir separador configurable (, vs ;)
  3. Soportar decimales con coma (locale)
  4. Calcular métricas por grupo (por ejemplo, por producto o categoria)
  5. Validar que el CSV tenga cabecera (y manejar caso contrario)

Lo que aprendiste

  • Lectura de CSV con csv.DictReader
  • Manejo de datos “sucios” y filas inválidas
  • Agregaciones básicas (conteo, suma, promedio)
  • Tests con archivos temporales (tmp_path)

Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.

Continúa con Reto #16 — Merge de dos listas ordenadas para practicar lógica de “dos punteros”, muy útil en algoritmos y rendimiento.