lección 3
Tipos de datos: estructurados, semiestructurados y no estructurados
Los tres reinos de los datos: tablas ordenadas, documentos flexibles y el caos creativo. Aprende a reconocer cada uno.
⏱ 55 min
No todos los datos nacen iguales. Cuando alguien dice "tenemos muchos datos", la primera pregunta que hay que hacer es: ¿de qué tipo? Porque no es lo mismo una tabla de ventas con columnas fijas que un directorio de archivos PDF o un volcado de mensajes de chat donde cada mensaje tiene campos diferentes. El tipo determina cómo lo almacenas, cómo lo procesas y qué herramientas usas.
Piensa en una librería. Los datos estructurados son el catálogo: cada libro tiene título, autor, ISBN, año y precio — siempre los mismos campos, siempre el mismo formato. Los datos semiestructurados son las reseñas de los clientes: tienen cierta estructura (autor, fecha, puntuación) pero el texto de la reseña varía en longitud y contenido. Los datos no estructurados son las fotos del evento de presentación de un libro: no tienen campos definidos, son binarios, y extraer información de ellas requiere técnicas especiales.
### Datos estructurados: el mundo de las tablas
Los datos estructurados encajan perfectamente en una tabla con filas y columnas. Cada columna tiene un tipo definido (texto, número, fecha) y cada fila sigue exactamente el mismo esquema. Son los datos de toda la vida: la tabla de clientes de una tienda, la de productos de un almacén, la de transacciones de un banco. La mayor parte de tu trabajo va a ser con datos estructurados.
1# Datos ESTRUCTURADOS: como una hoja de cálculo perfecta2# Cada registro tiene EXACTAMENTE los mismos campos34clientes = [5 {"id": 1, "nombre": "Ana López", "edad": 28, "ciudad": "Madrid", "vip": True},6 {"id": 2, "nombre": "Carlos Ruiz", "edad": 35, "ciudad": "Barcelona", "vip": False},7 {"id": 3, "nombre": "Laura Sanz", "edad": 42, "ciudad": "Sevilla", "vip": True},8]910# Todos tienen: id (entero), nombre (texto), edad (entero), ciudad (texto), vip (booleano)11# No hay sorpresas. Predecible. Fácil de procesar.12for c in clientes:13 print(f" {c['id']:3d} | {c['nombre']:15} | {c['edad']:3d} | {c['ciudad']:12} | VIP: {c['vip']}")
Datos estructurados: esquema fijo, tipos consistentes, como una hoja de cálculo
- Ventaja: predecible. Sabes exactamente qué campos tiene cada registro.
- Ventaja: eficiente. Las herramientas pueden optimizar porque conocen la estructura.
- Ventaja: consultable. Puedes hacer preguntas precisas ("clientes VIP de Madrid").
- Desventaja: rígido. Si mañana necesitas un campo nuevo, hay que modificar el esquema.
- Desventaja: no todo encaja. ¿Cómo metes una imagen o un PDF en una tabla?
### Datos semiestructurados: flexibilidad con cierto orden
Los datos semiestructurados tienen estructura, pero no rígida. El ejemplo más común es JSON: cada documento tiene campos, pero distintos documentos pueden tener campos diferentes. No necesitas definir el esquema por adelantado. Es el formato de la web moderna: las APIs devuelven JSON, los logs de aplicaciones son JSON, los archivos de configuración son JSON o YAML.
1# Datos SEMIESTRUCTURADOS: estructura flexible2# Cada evento tiene campos diferentes según el tipo34eventos = [5 {6 "tipo": "compra",7 "usuario": 42,8 "timestamp": "2026-01-15T10:30:00",9 "producto": "Teclado mecánico",10 "importe": 89.90,11 "metodo_pago": "tarjeta"12 },13 {14 "tipo": "login",15 "usuario": 42,16 "timestamp": "2026-01-15T10:28:00",17 "ip": "192.168.1.100",18 "dispositivo": "móvil"19 # No tiene "producto" ni "importe" -- y está bien!20 },21 {22 "tipo": "error",23 "timestamp": "2026-01-15T10:35:00",24 "codigo": 500,25 "mensaje": "Timeout en pasarela de pago",26 "stack_trace": "File app.py, line 42..."27 # No tiene "usuario" -- fue un error de sistema28 }29]3031# Mismo concepto (evento), pero campos diferentes según contexto.32for e in eventos:33 print(f" [{e['tipo']:8}] campos: {list(e.keys())}")
Datos semiestructurados: cada documento puede tener campos distintos
La flexibilidad es una bendición y una maldición. Bendición porque puedes evolucionar sin romper nada: si mañana los eventos de compra necesitan un campo "cupon_descuento", lo añades solo a los nuevos — los antiguos siguen funcionando. Maldición porque nunca puedes asumir que un campo existe: siempre tienes que comprobar antes de acceder ("¿tiene este evento el campo importe?"). Eso hace el código más defensivo y complejo.
### Datos no estructurados: el caos creativo
Los datos no estructurados no tienen un esquema definido en absoluto. Son archivos binarios, texto libre, imágenes, audio, vídeo. Para un ordenador, una imagen es simplemente una secuencia de bytes que representan píxeles — no hay "columnas" ni "campos". Extraer información útil de datos no estructurados requiere técnicas especiales (visión artificial, procesamiento de lenguaje natural, etc.) que están fuera del scope de esta skill.
- Imágenes y fotos: una radiografía, la foto de un producto, un selfie.
- Audio y vídeo: una llamada de atención al cliente, una videoconferencia grabada.
- Texto libre: un email, un comentario en redes sociales, un documento Word.
- PDFs escaneados: facturas, contratos, formularios.
- Código fuente: los archivos .py que escribes son, para otro sistema, texto libre sin estructura.
La mayor parte de lo que se guarda en el mundo es no estructurado — fotos, vídeo, audio, texto libre — sencillamente porque un vídeo ocupa muchísimo más que una fila de una tabla. Verás citada la cifra del 80% por todas partes; viene de un informe de hace más de una década que casi nadie ha leído, así que tómala como lo que es: una forma de decir «muchísimo». Y aun así, casi todo tu trabajo va a ser con datos estructurados y semiestructurados, porque son los que alimentan una decisión directamente. Lo no estructurado normalmente pasa antes por un proceso que lo convierte en tabla: un modelo que lee facturas en PDF y saca el importe, la fecha y el proveedor.
### Cómo convertir semiestructurado en estructurado
Aplanar datos semiestructurados — coger el JSON que devuelve una API y convertirlo en una tabla — es de las cosas que más veces vas a hacer, vayas por donde vayas. Si trabajas con informes, es el paso previo a poder cruzar esos datos con cualquier otra cosa. Es como tomar un documento con viñetas anidadas y convertirlo en una hoja de cálculo plana. No siempre es trivial — especialmente cuando hay arrays o objetos anidados — pero es una habilidad que usarás constantemente.
1# Convertir JSON semiestructurado → tabla estructurada2import json34# Datos de una API (semiestructurados)5respuesta_api = [6 {"id": 1, "nombre": "Ana", "direccion": {"ciudad": "Madrid", "cp": "28001"}},7 {"id": 2, "nombre": "Pedro", "direccion": {"ciudad": "Barcelona", "cp": "08001"}},8 {"id": 3, "nombre": "Lucía", "direccion": None}, # Sin dirección!9]1011# Aplanar: extraer campos anidados a nivel plano12tabla = []13for registro in respuesta_api:14 fila = {15 "id": registro["id"],16 "nombre": registro["nombre"],17 "ciudad": registro["direccion"]["ciudad"] if registro["direccion"] else None,18 "cp": registro["direccion"]["cp"] if registro["direccion"] else None,19 }20 tabla.append(fila)2122# Ahora es estructurado: todos los registros tienen los mismos campos23for fila in tabla:24 print(fila)
Aplanar JSON anidado en una tabla plana
Consejo de senior: cuando aplanes datos semiestructurados, SIEMPRE maneja el caso None/null. Las APIs del mundo real devuelven campos opcionales, objetos nulos y arrays vacíos. Si no lo previenes, tu código explotará a las 3AM del primer lunes de mes.
### Ejemplos reales por industria
- E-commerce: pedidos (estructurado), catálogo con atributos variables (semi), fotos de producto (no estructurado).
- Banca: transacciones (estructurado), logs de sesión del usuario (semi), documentos de identidad escaneados (no).
- Salud: historial clínico tabular (estructurado), notas del médico en texto libre (no), radiografías (no).
- Redes sociales: tabla de usuarios (estructurado), publicaciones con campos variables (semi), vídeos e imágenes (no).
- Logística: rutas y entregas (estructurado), eventos GPS con metadatos variables (semi), firmas digitalizadas (no).
Trampa real que he visto en producción: tratar datos semiestructurados como si fueran estructurados. "Asumimos que todos los eventos de la API tienen campo precio" — hasta que un día llega un evento sin ese campo y el pipeline explota. NUNCA asumas que un campo existe en datos semiestructurados. Siempre usa .get() con valor por defecto o comprueba con "if campo in registro".
El warning de arriba habla de .get() y de "campo" in dict. Si los recuerdas de Python, aquí van las dos juntas: .get() te da un valor seguro para operar, y "in" te dice si el campo existe — que no es lo mismo que si vale cero.
1# Dos herramientas para campos que pueden no existir:2evento = {"tipo": "login", "usuario": 42}34print(evento.get("importe", 0)) # 0 <- valor por defecto si no existe5print("importe" in evento) # False <- ¿está el campo, sí o no?
.get() para operar seguro, "in" para preguntar si existe
### Resumen práctico
- 01.Estructurado = tabla con esquema fijo. Lo más fácil de procesar. CSV, bases de datos.
- 02.Semiestructurado = documentos con estructura flexible. JSON, XML, logs. Requiere más cuidado.
- 03.No estructurado = sin esquema. Imágenes, vídeo, texto libre. Requiere técnicas especiales.
- 04.Tu trabajo principal será con estructurados y semiestructurados.
- 05.Convertir semi → estructurado (aplanar JSON) es una tarea diaria, y la vas a repetir en Pandas con una sola línea cuando llegues allí.
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...