lección 3

Listas y diccionarios

Las dos estructuras de datos que usarás el 90% del tiempo como ingeniero de datos: listas para secuencias y diccionarios para registros.

75 min

### El problema: un programa necesita organizar GRUPOS de datos

Hasta ahora, cada dato que has manejado vivía en una variable individual. Una venta, un precio, un nombre. Pero piensa en el mundo real: una empresa no tiene UNA venta — tiene miles. Un servidor no genera UN log — genera millones. Un equipo de ventas no tiene UN cliente — tiene una cartera entera. Las variables sueltas no escalan. Necesitas una forma de organizar COLECCIONES de datos relacionados.

Este es el problema fundamental que resuelven las estructuras de datos: dar forma y organización a GRUPOS de información para que puedas buscar, filtrar, ordenar, agrupar y transformar de forma eficiente. Sin ellas, tu programa sería como una oficina donde cada documento está suelto encima de una mesa infinita — técnicamente toda la información está ahí, pero encontrar algo es imposible.

### Antes de los ordenadores: fichas, archivadores y catálogos

Las estructuras de datos no nacieron con la programación — son mucho más antiguas. Piensa en cómo se organizaba la información antes de los ordenadores. Una biblioteca tiene un catálogo de fichas: cada ficha contiene autor, título, editorial y una referencia a la ubicación física del libro. Las fichas están ordenadas alfabéticamente para poder buscar. Eso es una estructura de datos: información organizada con un criterio que facilita su uso.

O piensa en un archivador de oficina. Cada cajón tiene una etiqueta (A-F, G-L...). Dentro del cajón, las carpetas están ordenadas. Dentro de cada carpeta hay documentos relacionados. Este sistema jerárquico permite que una persona encuentre el expediente de un cliente entre miles en menos de un minuto. Sin la estructura, ese mismo trabajo tomaría horas de rebuscar en montones de papel.

Los programadores adoptaron estas metáforas directamente. Una lista es como una estantería con casillas numeradas — accedes por posición. Un diccionario es como un archivador con etiquetas — accedes por nombre. Y como verás, el 90% del trabajo con datos en Python se reduce a combinar estas dos ideas: secuencias ordenadas y mapeos de clave a valor.

Dos formas de organizar datos: por posicion (lista) o por nombre (diccionario). Todo lo demas se construye sobre estas dos ideas.

### Por que estas dos estructuras son EL 90% de tu vida como ingeniero de datos

No es una exageracion. Mira cualquier pipeline de datos real y veras el mismo patron una y otra vez: los datos llegan como una LISTA de REGISTROS. Cada registro es un DICCIONARIO con campos nombrados. Un CSV es una lista de filas. Un JSON de una API es una lista de objetos. Una tabla de base de datos es una lista de filas con columnas nombradas. Pandas DataFrames, PySpark DataFrames, resultados de consultas SQL — todo se reduce a la misma estructura: una secuencia de mapeos clave-valor.

Cuando mas adelante uses Pandas y escribas df.groupby("categoria").sum(), lo que Pandas esta haciendo por debajo es exactamente lo que vas a aprender hoy: recorrer una lista de registros, acceder a claves especificas y acumular resultados. La unica diferencia es que Pandas lo hace mas rapido y con menos codigo. Pero la LOGICA es identica. Por eso empezamos aqui: si dominas listas y diccionarios puros, Pandas y PySpark seran una extension natural, no una caja negra magica.

Consejo de senior: cada vez que te enfrentes a un problema de datos nuevo, preguntate primero: "¿mis datos son una lista de cosas? ¿Cada cosa tiene campos con nombre?" Si la respuesta es si (y casi siempre lo es), ya sabes la estructura: lista de diccionarios. Ese modelo mental te resuelve el 90% de los problemas antes de escribir una sola linea de codigo.

### De variables sueltas a colecciones: el salto conceptual

Imagina que tu jefa te dice: "necesito el total de ventas de la semana". Si solo tienes variables sueltas, tu codigo se ve asi: total = venta_lunes + venta_martes + venta_miercoles + venta_jueves + venta_viernes. Cinco variables, una suma manual. Funciona. Pero ahora te dice: "necesito el total del mes". De repente tienes 30 variables. Y si te dice "necesito el total del anio"... 365 variables. Eso no escala.

Con una lista, el mismo problema se resuelve sin importar si son 5 datos, 30 o 365: total = sum(ventas). Una linea. Y si manana te piden "el total de los ultimos 3 anios", sigue siendo la misma linea — solo cambia el contenido de la lista. Esa es la potencia de las estructuras de datos: abstraen la CANTIDAD para que tu logica no dependa de cuantos elementos hay.

Error clasico de principiante: crear variables numeradas (venta1, venta2, venta3...) en vez de usar una lista. Si te ves escribiendo variable1, variable2, variable3 — para. Eso es una lista disfrazada. Usala como tal: ventas = [valor1, valor2, valor3]. Tu codigo sera mas corto, mas flexible y mas facil de mantener.

Ahora que entiendes QUE problema resuelven las estructuras de datos y POR QUE son fundamentales, vamos a dominar las dos que usaras cada dia de tu carrera: listas y diccionarios.

### Listas: secuencias ordenadas de datos

Una lista es una colección ordenada de elementos. Imagina una fila de cajas numeradas (empezando por 0, no por 1 — veremos por qué). Puedes poner cualquier cosa dentro de cada caja: números, textos, otras listas, incluso diccionarios. Y puedes añadir cajas, quitar cajas o reorganizarlas en cualquier momento.

1# Una lista de ventas diarias (en euros)
2ventas_semana = [1250.00, 980.50, 1100.75, 1430.20, 890.00, 1560.80, 2100.00]
3
4# Acceder por índice (empiezan en 0)
5print(ventas_semana[0]) # 1250.00 — lunes (primer día)
6print(ventas_semana[-1]) # 2100.00 — domingo (último día)
7
8# Slicing: obtener un rango
9entre_semana = ventas_semana[0:5] # lunes a viernes
10fin_de_semana = ventas_semana[5:] # sábado y domingo
11print(f"Entre semana: {entre_semana}")
12print(f"Fin de semana: {fin_de_semana}")

Las listas son secuencias indexadas. Los índices empiezan en 0.

¿Por qué empiezan en 0 y no en 1? Es una herencia de C y la aritmética de punteros. El índice representa el "desplazamiento" desde el inicio. El primer elemento está a 0 posiciones del inicio. Suena raro al principio, pero te acostumbras rápido y tiene ventajas matemáticas (el slicing funciona como intervalos semiabiertos [inicio, fin)).

### Operaciones esenciales con listas

1# Crear y modificar listas
2productos_stock = ["laptop", "monitor", "teclado", "ratón"]
3
4# Añadir elementos
5productos_stock.append("webcam") # Añade al final
6productos_stock.insert(0, "servidor") # Inserta en posición 0
7
8# Eliminar elementos
9productos_stock.remove("ratón") # Elimina por valor
10eliminado = productos_stock.pop() # Elimina y devuelve el último
11
12# Longitud
13print(f"Productos en stock: {len(productos_stock)}")
14
15# Ordenar
16precios = [299.99, 49.99, 899.00, 129.50, 1499.00]
17precios.sort() # Ordena la lista original (in-place)
18precios_desc = sorted(precios, reverse=True) # Crea nueva lista ordenada
19
20# Buscar
21print("laptop" in productos_stock) # True o False
22print(precios.index(899.00)) # Posición del elemento

Las operaciones más comunes: añadir, eliminar, ordenar, buscar.

### List comprehensions: el superpoder de Python

Las list comprehensions son la forma pythónica de crear listas a partir de otras listas. En vez de escribir un bucle for de 4 líneas, lo resuelves en 1. Para datos, esto es fundamental — constantemente filtras, transformas y mapeas listas de valores.

1# Tenemos precios sin IVA
2precios_sin_iva = [100, 250, 49.99, 899, 1299.50]
3
4# Calcular precios con IVA (21%) — SIN list comprehension
5precios_con_iva = []
6for precio in precios_sin_iva:
7 precios_con_iva.append(precio * 1.21)
8
9# Lo MISMO con list comprehension (1 línea)
10precios_con_iva = [precio * 1.21 for precio in precios_sin_iva]
11print(precios_con_iva)
12
13# Filtrar: solo precios mayores a 200€
14caros = [p for p in precios_con_iva if p > 200]
15print(f"Productos caros (>200€): {caros}")
16
17# Transformar: redondear a 2 decimales
18redondeados = [round(p, 2) for p in precios_con_iva]
19print(f"Redondeados: {redondeados}")

List comprehensions: filtrar y transformar en una sola línea expresiva.

Consejo de senior: si tu list comprehension tiene más de 80 caracteres o incluye lógica compleja, usa un bucle for normal. La legibilidad siempre gana. Una list comprehension ilegible es PEOR que un bucle claro de 4 líneas.

### Diccionarios: datos con nombre

Si una lista es una fila de cajas numeradas, un diccionario es un archivador con etiquetas. En vez de acceder por posición (índice 0, 1, 2...), accedes por nombre (clave). Cada registro de datos en el mundo real tiene campos con nombre: un cliente tiene "nombre", "email", "edad". Eso es un diccionario.

Los diccionarios son la estructura fundamental para representar un REGISTRO de datos — una fila de una tabla, un objeto JSON, una entidad de negocio. Cuando tu pipeline lee un JSON de una API, lo que obtienes es un diccionario (o una lista de diccionarios).

1# Un registro de venta como diccionario
2venta = {
3 "id": "VNT-2024-001",
4 "fecha": "2024-01-15",
5 "cliente": "María García",
6 "producto": "Monitor 4K",
7 "cantidad": 2,
8 "precio_unitario": 349.99,
9 "impuesto": 0.21,
10}
11
12# Acceder a valores por clave
13print(venta["producto"]) # "Monitor 4K"
14print(venta["precio_unitario"]) # 349.99
15
16# Acceso seguro con .get() (no explota si la clave no existe)
17descuento = venta.get("descuento", 0) # 0 si no existe
18print(f"Descuento: {descuento}")
19
20# Añadir/modificar campos
21venta["total"] = venta["cantidad"] * venta["precio_unitario"] * (1 + venta["impuesto"])
22print(f"Total: {venta['total']:.2f}€")

Un diccionario es un registro de datos con campos nombrados.

### Listas de diccionarios: tus futuros DataFrames

Aquí es donde todo converge. Una tabla de datos no es más que una LISTA de DICCIONARIOS. Cada diccionario es una fila. Cada clave es una columna. Cuando en futuras skills uses Pandas o PySpark, por debajo son exactamente esto — pero con superpoderes. Primero domina la versión pura.

1# Una "tabla" de ventas como lista de diccionarios
2ventas = [
3 {"fecha": "2024-01-15", "producto": "Laptop", "importe": 1299.00},
4 {"fecha": "2024-01-15", "producto": "Monitor", "importe": 349.99},
5 {"fecha": "2024-01-16", "producto": "Teclado", "importe": 79.99},
6 {"fecha": "2024-01-16", "producto": "Laptop", "importe": 1299.00},
7 {"fecha": "2024-01-17", "producto": "Ratón", "importe": 29.99},
8]
9
10# Filtrar: ventas de más de 100€
11grandes = [v for v in ventas if v["importe"] > 100]
12print(f"Ventas grandes: {len(grandes)}")
13
14# Transformar: extraer solo importes
15importes = [v["importe"] for v in ventas]
16print(f"Total facturado: {sum(importes):.2f}€")
17
18# Agrupar: ventas por producto
19from collections import Counter
20productos_vendidos = [v["producto"] for v in ventas]
21conteo = Counter(productos_vendidos)
22print(f"Ventas por producto: {dict(conteo)}")

Lista de diccionarios = tabla de datos. Esta estructura es fundamental.

Esto es exactamente lo que Pandas y PySpark hacen — pero con más potencia

### Métodos esenciales de diccionarios

1cliente = {
2 "nombre": "Carlos López",
3 "email": "carlos@empresa.com",
4 "plan": "premium",
5 "gasto_mensual": 450.00,
6}
7
8# Obtener todas las claves y valores
9print(list(cliente.keys())) # ["nombre", "email", "plan", "gasto_mensual"]
10print(list(cliente.values())) # ["Carlos López", "carlos@empresa.com", ...]
11
12# Iterar sobre clave-valor (muy común en datos)
13for campo, valor in cliente.items():
14 print(f" {campo}: {valor}")
15
16# Actualizar múltiples campos de golpe
17cliente.update({"plan": "enterprise", "gasto_mensual": 890.00})
18
19# Eliminar una clave
20del cliente["email"]
21
22# Copiar (cuidado: = NO copia, crea una referencia)
23cliente_copia = cliente.copy()

keys(), values(), items(), update() y copy() — los métodos que más usarás.

Cuidado con la asignación de diccionarios: si haces "copia = original", ambas variables apuntan al MISMO diccionario. Modificar uno modifica el otro. Usa .copy() para una copia independiente. Este bug es sutil y he visto a seniors quemarse horas por él.

En ingeniería de datos, el patrón más común es: leer datos → lista de diccionarios → transformar con list comprehensions → escribir resultado. Domina ese flujo y dominas el 80% del trabajo con datos puros en Python.

## ejercicios

[01]

Filtrar ventas VIP

El equipo de marketing quiere contactar a los clientes que han gastado más de 500€ este mes. Tienes una lista de diccionarios con ventas. Filtra las que superen 500€ y calcula el total de esas ventas VIP.

Cargando editor...
[02]

Agrupar productos por categoría

Tienes una lista de productos con su categoría. Crea un diccionario donde cada clave sea una categoría y el valor sea la lista de productos de esa categoría.

Cargando editor...
[03]

Enriquecer registros de ventas

Cada venta tiene precio_unitario y cantidad. Añade a cada registro un campo "total" (precio * cantidad) y un campo "categoria_importe" que sea "pequeña" (<100), "mediana" (100-500) o "grande" (>500).

Cargando editor...
[04]

Mini dashboard con diccionarios

Crea un diccionario "reporte" con las claves: total_ventas, num_dias, promedio_diario, mejor_dia y peor_dia. Calcula cada valor a partir de los datos de ventas diarias proporcionados.

Cargando editor...

Regístrate para guardar tu progreso.

## comentarios

Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.

Inicia sesión para comentar y responder.

cargando comentarios...