Un análisis de datos completo sigue cinco etapas: cargar los datos, limpiarlos, explorarlos, calcular métricas clave y comunicar los resultados con gráficas.
En esta lección integras todo lo que aprendiste en el curso. Vas a construir un proyecto real, paso a paso, usando un dataset de ventas de una empresa mexicana.
Las cinco etapas del análisis
Todo proyecto de análisis de datos sigue la misma estructura básica.
| Etapa | Pregunta que responde |
|---|---|
| 1. Cargar | ¿Qué datos tengo? |
| 2. Limpiar | ¿Los datos son confiables? |
| 3. Explorar | ¿Qué patrones existen? |
| 4. Métricas | ¿Cuáles son los números clave? |
| 5. Visualizar | ¿Cómo comunico los resultados? |
Seguir este orden te evita errores costosos. Nunca hagas métricas sobre datos sucios.
Etapa 1: Cargar los datos
El proyecto usa un dataset de ventas de Liverpool con tres columnas: fecha, producto y monto.
import pandas as pd
import matplotlib.pyplot as plt
# Cargar el dataset
df = pd.read_csv("ventas_liverpool.csv")
# Vista inicial
print(df.shape) # Cuántas filas y columnas
print(df.dtypes) # Tipo de cada columna
print(df.head()) # Primeras filas
df.shape te dice el tamaño total del dataset. df.dtypes revela si los números se guardaron como texto, un error muy común.
Etapa 2: Limpiar los datos
Limpiar significa eliminar lo que distorsiona el análisis. Revisa tres cosas: valores nulos, duplicados y tipos de datos incorrectos.
# Revisar nulos
print(df.isnull().sum())
# Eliminar filas con nulos en columnas críticas
df = df.dropna(subset=["monto", "fecha"])
# Eliminar duplicados
df = df.drop_duplicates()
# Convertir fecha a tipo datetime
df["fecha"] = pd.to_datetime(df["fecha"])
# Convertir monto a numérico (por si venía como texto)
df["monto"] = pd.to_numeric(df["monto"], errors="coerce")
# Eliminar filas donde monto no se pudo convertir
df = df.dropna(subset=["monto"])
print(f"Registros limpios: {len(df)}")
Después de limpiar, siempre imprime cuántos registros quedaron. Así detectas si perdiste demasiados datos.
Regla práctica: si pierdes más del 10% de los registros al limpiar, investiga por qué. Puede ser un problema en la fuente original.
Etapa 3: Explorar los datos
La exploración responde preguntas básicas antes de hacer cálculos formales.
# Rango de fechas del dataset
print("Inicio:", df["fecha"].min())
print("Fin:", df["fecha"].max())
# Productos únicos
print("Productos:", df["producto"].nunique())
print(df["producto"].value_counts().head(5))
# Estadísticas del monto
print(df["monto"].describe())
describe() muestra el mínimo, máximo, promedio y percentiles de una columna numérica. Es el resumen más rápido que existe.
Si el máximo es mucho mayor que el percentil 75, hay valores atípicos. Revísalos antes de sacar promedios.
Etapa 4: Calcular métricas clave
Aquí aplicas groupby(), merge() y operaciones de agregación para extraer información útil.
4a. Ventas totales por mes
# Crear columna de mes
df["mes"] = df["fecha"].dt.to_period("M")
# Ventas totales por mes
ventas_mes = df.groupby("mes")["monto"].sum().reset_index()
ventas_mes.columns = ["mes", "total_ventas"]
print(ventas_mes)
Resultado esperado:
mes total_ventas
0 2024-01 412500
1 2024-02 389000
2 2024-03 521300
Formateado: el mes de enero tuvo $412,500 en ventas, febrero $389,000 y marzo $521,300.
4b. Producto más vendido
# Top 5 productos por monto total
top_productos = (
df.groupby("producto")["monto"]
.sum()
.sort_values(ascending=False)
.head(5)
.reset_index()
)
top_productos.columns = ["producto", "total"]
print(top_productos)
4c. Ticket promedio por producto
# Promedio de venta por producto
ticket = df.groupby("producto")["monto"].mean().reset_index()
ticket.columns = ["producto", "ticket_promedio"]
ticket["ticket_promedio"] = ticket["ticket_promedio"].round(2)
print(ticket.sort_values("ticket_promedio", ascending=False).head(5))
El ticket promedio mide cuánto gasta un cliente en promedio por transacción. Es una métrica clave en retail.
4d. Cruzar con catálogo de productos
# Cargar catálogo con categoría de cada producto
catalogo = pd.read_csv("catalogo_productos.csv")
# Merge para agregar la categoría
df_completo = df.merge(catalogo, on="producto", how="left")
# Ventas por categoría
ventas_categoria = (
df_completo.groupby("categoria")["monto"]
.sum()
.sort_values(ascending=False)
.reset_index()
)
print(ventas_categoria)
Usas how="left" para conservar todas las ventas aunque algún producto no esté en el catálogo.
Etapa 5: Visualizar los resultados
Las gráficas comunican lo que los números no pueden solos.
Gráfica 1: Ventas por mes (línea)
plt.figure(figsize=(10, 4))
plt.plot(ventas_mes["mes"].astype(str), ventas_mes["total_ventas"], marker="o", color="royalblue")
plt.title("Ventas mensuales - Liverpool 2024")
plt.xlabel("Mes")
plt.ylabel("Total ($)")
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("ventas_mes.png")
plt.show()
Usa marker="o" para que cada punto sea visible. Usa savefig() para guardar la imagen y compartirla.
Gráfica 2: Top productos (barras horizontales)
plt.figure(figsize=(8, 5))
plt.barh(top_productos["producto"], top_productos["total"], color="steelblue")
plt.title("Top 5 productos por ventas")
plt.xlabel("Total vendido ($)")
plt.gca().invert_yaxis() # El más vendido arriba
plt.tight_layout()
plt.savefig("top_productos.png")
plt.show()
invert_yaxis() coloca el producto con más ventas en la parte superior. Es la convención estándar en gráficas de ranking.
Gráfica 3: Participación por categoría (pastel)
plt.figure(figsize=(6, 6))
plt.pie(
ventas_categoria["monto"],
labels=ventas_categoria["categoria"],
autopct="%1.1f%%",
startangle=90
)
plt.title("Participación de ventas por categoría")
plt.tight_layout()
plt.savefig("categorias.png")
plt.show()
autopct muestra el porcentaje dentro de cada rebanada. Usa este formato solo cuando tienes menos de seis categorías.
Errores comunes
Error 1: Hacer métricas antes de limpiar. Si calculas el promedio con valores nulos o duplicados, el resultado es incorrecto. Limpia siempre primero.
Error 2: Olvidar convertir la columna de fecha.
Sin pd.to_datetime(), no puedes extraer el mes ni ordenar por fecha. El error aparece hasta que intentas usar .dt.month.
Error 3: No verificar el resultado del merge.
Si el merge multiplica filas inesperadamente, hay duplicados en la columna llave del catálogo. Usa catalogo["producto"].value_counts() antes de hacer el merge.
Error 4: Graficar sin guardar.
En entornos de producción como un servidor o un script automático, plt.show() puede no funcionar. Usa siempre plt.savefig() antes de plt.show().
Error 5: No documentar el código. Un análisis sin comentarios es difícil de mantener. Agrega una línea de comentario en cada bloque principal para explicar qué hace.
Lo que aprendiste en este curso
Este curso te dio las herramientas fundamentales del análisis de datos con Python.
| Lección | Habilidad |
|---|---|
| 1–2 | Crear y manipular DataFrames con pandas |
| 3–4 | Filtrar, ordenar y transformar datos |
| 5 | Limpiar datos sucios con dropna() y fillna() |
| 6 | Agrupar con groupby() para calcular métricas |
| 7 | Visualizar con matplotlib |
| 8 | Unir tablas con merge() y concat() |
| 9 | Integrar todo en un proyecto completo |
Próximos pasos recomendados
Una vez que dominas este flujo básico, puedes avanzar hacia herramientas más potentes.
- Aprende
seabornpara gráficas estadísticas más elaboradas con menos código. - Explora SQL con pandas usando
read_sql()para conectarte directamente a bases de datos empresariales. - Practica con datos reales: el INEGI, el SAT y el portal de datos abiertos del gobierno mexicano publican datasets gratuitos.
- Automatiza tus reportes con scripts de Python programados en el STPS o sistemas internos de tu empresa.
- Aprende a presentar resultados exportando tablas a Excel con
to_excel()y gráficas en PDF para entregar a tu equipo.
El análisis de datos es una habilidad que se perfecciona con la práctica. Elige un problema real de tu trabajo o negocio y aplica este mismo flujo de cinco etapas.