Principales fuentes de datos¶
En cualquier proyecto de análisis de datos o Data Science los datos no aparecen por arte de magia en un entorno listo para trabajar. En el mundo real los datos residen en múltiples orígenes, se almacenan en diferentes formatos y presentan distintos niveles de estructura y rendimiento.
El primer paso de todo analista consiste en identificar la fuente de datos, comprender su formato subyacente y seleccionar las herramientas adecuadas para extraer, transformar y cargar (Extract, Transform, Load, ETL) esa información en su entorno de análisis.
A lo largo de esta sección exploraremos los orígenes de datos más habituales en la industria, desde los formatos más simples orientados a la práctica hasta soluciones optimizadas para alto rendimiento y consulta masiva.
1. Archivos planos: CSV¶
En primer lugar, hablaremos de información almacenada en archivos de texto plano. En este campo el formato más predominante es el formato CSV (Comma Separated Values), ampliamente extendido y fácil de inspeccionar, aunque ineficiente para grandes volúmenes de información.
Como su nombre indica, permite representar información en un fichero de texto, separándola por comas. La idea es almacenar en estos ficheros un conjunto de registros, de modo que cada registro se almacena en una línea, separando sus campos por comas (u otro delimitador, como por ejemplo el punto y coma).
La primera línea del fichero suele contener (aunque no es obligatorio) los títulos o cabeceras de cada columna de datos y, a continuación cada fila representa un registro del conjunto, dando valor a cada columna. El ejemplo de los libros anterior podríamos almacenarlo así:
titulo,autor,paginas,fechaPublicacion
El juego de Ender,Orson Scott Card,325,1985
La tabla de Flandes,Arturo Pérez Reverte,384,1990
...
Este formato de archivos se utiliza mucho en procesos de machine y deep learning, como punto de entrada al modelo que desarrollemos; la información con la que queremos entrenar al modelo para que aprenda típicamente se le proporciona en archivos de este tipo, a partir de los cuales es muy sencillo extraer la tabla de datos con la que trabajar. Sin embargo, resulta un formato ineficiente si la cantidad de datos a explorar es grande.
2. Archivos estructurados e intercambio web: JSON y APIs REST¶
Mientras que los archivos CSV almacenan la información de forma estrictamente tabular (filas y columnas), la mayor parte de los datos que circulan por internet o que generan las aplicaciones modernas se transfieren en formatos no tabulares o semiestructurados. Para cualquier analista de datos, saber interpretar, consultar y transformar estos formatos es una habilidad fundamental.
JSON es el estándar de facto para el intercambio de datos en la web. A diferencia de CSV, JSON no está restringido a una tabla fija; utiliza una estructura jerárquica basada en pares clave-valor y listas, muy similar a los diccionarios y listas de Python. Aquí vemos un ejemplo:
[{"titulo":"El juego de Ender","autor":"Orson Scott Card",
"paginas":325, "fechaPublicacion":1985},
{"titulo":"La tabla de Flandes","autor":"Arturo Pérez Reverte",
"paginas":384, "fechaPublicacion":1990}, ...]
2.1. Ejemplo práctico¶
Para poner en práctica el consumo de APIs utilizaremos alguna API pública de pruebas, como esta que obtiene un listado ficticio de productos de una tienda. Usaremos para ello la librería requests de Python, que deberemos instalar si no la tenemos ya (pip install requests):
import requests
url_api = "https://fakestoreapi.com/products"
# Realizar la solicitud GET al servidor
print("Enviando petición a la API...")
response = requests.get(url_api)
# Comprobar el código de estado HTTP
if response.status_code == 200:
# Conexión OK. Extraemos datos JSON
print("Conexión exitosa")
datos_json = response.json()
# Podemos acceder a algún dato para comprobar el funcionamiento
print("Primer título:", datos_json[0]["title"])
else:
print(f"Error al consultar la API. Código de estado: {response.status_code}")
Puedes consultar más información sobre requests en su web oficial.
3. Extracción directa: Web Scraping¶
El contenido que podemos encontrar en páginas web es normalmente contenido semiestructurado, en el sentido de que está embebido en etiquetas que nos permiten aislar ciertos componentes que nos interesen, como el texto de una reseña, o la fecha de publicación de un artículo. Sin embargo, es necesario identificar correctamente estas secciones y procesar adecuadamente el contenido HTML para extraer la información que nos sea relevante. Usaremos de nuevo la librería requests del apartado anterior para conectar con la web en cuestión, y beautifulsoup para extraer la información que nos interese.
Aquí vemos un ejemplo que obtiene todos los encabezados de nivel 2 (h2) de la página de Wikipedia que habla sobre Python:
import requests
from bs4 import BeautifulSoup
url = 'https://es.wikipedia.org/wiki/Python'
respuesta = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
if respuesta.status_code == 200:
soup = BeautifulSoup(respuesta.text, 'html.parser')
titulos = soup.body.find_all('h2')
for titulo in titulos:
print("* " + titulo.text)
4. Formatos binarios o columnares: Parquet¶
A medida que el volumen de datos crece, los formatos de archivo de texto plano como CSV empiezan a mostrar sus limitaciones: ocupan mucho espacio en disco, son lentos de leer y procesar, y no guardan información sobre los tipos de datos (como fechas o números enteros).
En entornos de datos modernos y Big Data, el estándar para almacenamiento eficiente es Apache Parquet, un formato binario y orientado a columnas. La diferencia clave entre un CSV y un Parquet radica en cómo organizan la información físicamente en el disco duro:
- Orientación por Filas (CSV): Los datos de un registro se guardan uno a continuación del otro. Si quieres calcular la media de una sola columna en un archivo con 50 columnas, el sistema debe leer todas las columnas de todas las filas del disco, desperdiciando tiempo y memoria.
- Orientación por Columnas (Parquet): Los datos de una misma columna se almacenan juntos. Si ejecutas una consulta para calcular el promedio de la columna
Precio, el motor de lectura solo lee esa columna del disco, ignorando las otras 49.
4.1. Ventajas e inconvenientes de Parquet¶
Entre las ventajas del formato Parquet, podemos citar las siguientes:
- Alta compresión: Al agrupar datos del mismo tipo en la misma columna, los algoritmos de compresión (como Snappy o Gzip) logran reducir el tamaño del archivo entre un 70% y un 90% comparado con un CSV.
- Conserva el esquema y tipos de datos: Guarda explícitamente los tipos de variables (
int32,float64,datetime,boolean). Al leer el archivo, no hay que redefinir los tipos de datos. - Lectura ultra rápida (Pushdown Filtering): Permite filtrar datos antes de cargarlos completamente en memoria RAM, leyendo únicamente las columnas o bloques necesarios.
Entre sus inconvenientes, podemos destacar:
- No es legible por humanos: Al ser un formato binario, no se puede abrir ni inspeccionar directamente con un bloc de notas o editor de texto.
- Requiere librerías especializadas: Necesita librerías como
pyarrowofastparquetpara leerse desde Python. - Ineficiente para escrituras continuas: No está pensado para insertar registros de uno en uno, sino para escrituras por lotes (batch).
4.2. Ejemplo práctico: Comparativa de rendimiento con Python¶
Para trabajar con Parquet en Pandas o Polars, se utiliza el motor de PyArrow (pip install pyarrow).
A continuación, crearemos un DataFrame con 1 millón de filas para comparar el espacio en disco y el tiempo de lectura entre CSV y Parquet:
import pandas as pd
import numpy as np
import time
import os
# 1. Crear un DataFrame sintético con 1 millón de filas
n_filas = 1_000_000
df_grande = pd.DataFrame({
'id': np.arange(n_filas),
'categoria': np.random.choice(['A', 'B', 'C', 'D'], size=n_filas),
'valor': np.random.randn(n_filas),
'fecha': pd.date_range('2025-01-01', periods=n_filas, freq='s')
})
# 2. Guardar en formato CSV y Parquet
df_grande.to_csv('datos.csv', index=False)
df_grande.to_parquet('datos.parquet', index=False)
# 3. Comparar peso de los archivos en disco
peso_csv = os.path.getsize('datos.csv') / (1024 * 1024)
peso_parquet = os.path.getsize('datos.parquet') / (1024 * 1024)
print(f"Tamaño en disco CSV: {peso_csv:.2f} MB")
print(f"Tamaño en disco Parquet: {peso_parquet:.2f} MB (¡Mucho más pequeño!)")
# 4. Comparar velocidad de lectura
# Lectura CSV
inicio = time.time()
_ = pd.read_csv('datos.csv')
tiempo_csv = time.time() - inicio
# Lectura Parquet
inicio = time.time()
_ = pd.read_parquet('datos.parquet')
tiempo_parquet = time.time() - inicio
print(f"\nTiempo de lectura CSV: {tiempo_csv:.4f} segundos")
print(f"Tiempo de lectura Parquet: {tiempo_parquet:.4f} segundos")
5. Bases de datos SQL y NoSQL¶
En el entorno profesional, los datos raramente están esperándonos en un archivo local comprimido o en un CSV formateado. La inmensa mayoría de la información corporativa reside en bases de datos, infraestructuras diseñadas para almacenar, gestionar y servir grandes volúmenes de datos de forma segura, concurrente y eficiente.
A día de hoy, podemos distinguir dos grandes grupos o tipos de bases de datos:
- Bases de datos relacionales (SQL): Organizan la información en tablas rígidas compuestas por filas y columnas, conectadas entre sí mediante relaciones (claves primarias y ajenas). Se consultan mediante SQL (Structured Query Language), el estándar universal de la industria. Ejemplos típicos son sistemas de transacciones bancarias, gestión de clientes (CRM) u otros escenarios donde la integridad de los datos sea importante.
- Bases de datos no relacionales (NoSQL): Diseñadas para gestionar datos no estructurados o semiestructurados que no encajan fácilmente en una tabla rígida, o para aplicaciones que requieren escalar horizontalmente a gran velocidad. Tienen esquemas flexibles para almacenar la información, pudiendo tener cada registro una estructura distinta. Existen distintos tipos, como las bases de datos documentales (como MongoDB) o los pares clave-valor (Redis), etc. Los casos de uso típicos se centran en redes sociales (posts con comentarios asociados), registros de actividad (logs), etc.
En este documento puedes aprender más sobre cómo acceder a bases de datos relacionales (como MySQL) y no relacionales (como MongoDB) usando Python.