Una tienda de electrónica con más de 15,000 transacciones anuales tenía sus datos completamente dispersos: archivos Excel sin estructura, sin métricas consolidadas y sin visibilidad real del negocio. Se construyó un pipeline completo desde la base de datos hasta un dashboard ejecutivo en Excel, pasando por limpieza y análisis con Python.
-- Extracción consolidada de ventas 2024 -- JOIN entre ventas, productos y clientes SELECT v.id_venta, v.fecha_venta, DATE_FORMAT(v.fecha_venta, '%Y-%m') AS mes, c.nombre_cliente, c.region, p.nombre_producto, p.categoria, v.cantidad, v.precio_unitario, (v.cantidad * v.precio_unitario) AS ingreso_total, v.estado_venta, v.canal_venta FROM ventas v INNER JOIN productos p ON v.id_producto = p.id_producto INNER JOIN clientes c ON v.id_cliente = c.id_cliente WHERE v.fecha_venta BETWEEN '2024-01-01' AND '2024-12-31' AND v.estado_venta != 'cancelado' ORDER BY v.fecha_venta DESC;
-- KPIs por categoría con ranking -- CTE + función de ventana RANK() WITH ventas_cat AS ( SELECT p.categoria, COUNT(v.id_venta) AS total_ventas, SUM(v.cantidad * v.precio_unitario) AS ingresos, AVG(v.precio_unitario) AS ticket_prom, COUNT(DISTINCT v.id_cliente) AS clientes_unicos FROM ventas v JOIN productos p ON v.id_producto = p.id_producto WHERE v.estado_venta = 'completado' GROUP BY p.categoria ) SELECT *, RANK() OVER ( ORDER BY ingresos DESC ) AS ranking_ingreso FROM ventas_cat ORDER BY ranking_ingreso;
import pandas as pd import matplotlib.pyplot as plt import matplotlib.ticker as mticker # ── 1. CARGA Y LIMPIEZA ──────────────────────────────────────────── df = pd.read_csv('ventas_2024.csv', parse_dates=['fecha_venta']) # Eliminar duplicados y filas sin ingreso df = df.drop_duplicates(subset='id_venta') df = df.dropna(subset=['ingreso_total', 'categoria']) # Crear columnas derivadas df['mes'] = df['fecha_venta'].dt.to_period('M') df['trimestre'] = df['fecha_venta'].dt.to_period('Q') df['dia_semana'] = df['fecha_venta'].dt.day_name() # ── 2. MÉTRICAS CLAVE ────────────────────────────────────────────── ingreso_total = df['ingreso_total'].sum() ticket_prom = df['ingreso_total'].mean() total_ventas = df['id_venta'].nunique() tasa_devol = (df['estado_venta'] == 'devuelto').mean() * 100 # ── 3. AGRUPACIONES PARA DASHBOARD ───────────────────────────────── ventas_mes = ( df.groupby('mes')['ingreso_total'] .sum().reset_index() ) top_productos = ( df.groupby('nombre_producto')['ingreso_total'] .sum().nlargest(5) ) cat_ingresos = ( df.groupby('categoria')['ingreso_total'].sum() ) # ── 4. EXPORTAR A EXCEL CON MÚLTIPLES HOJAS ──────────────────────── with pd.ExcelWriter( 'reporte_ventas_2024.xlsx', engine='openpyxl' ) as writer: df.to_excel(writer, sheet_name='Datos_Limpios', index=False) ventas_mes.to_excel(writer, sheet_name='Ventas_Mensual', index=False) top_productos.to_excel(writer, sheet_name='Top_Productos') cat_ingresos.to_excel(writer, sheet_name='Por_Categoria') print(f"✓ Reporte generado — {total_ventas:,} ventas procesadas") print(f" Ingresos totales : ${ingreso_total:,.2f}") print(f" Ticket promedio : ${ticket_prom:,.2f}") print(f" Tasa devolución : {tasa_devol:.1f}%")
| # | Producto | Categoría | Unidades | Ingreso Total | % del Total | Tendencia | Estado |
|---|---|---|---|---|---|---|---|
| 01 | MacBook Air M2 | Laptops | 342 | $409,524 |
28.4%
|
↑ +22% | Top |
| 02 | iPhone 15 Pro | Smartphones | 521 | $364,700 |
25.3%
|
↑ +15% | Top |
| 03 | Sony WH-1000XM5 | Audio | 893 | $178,600 |
12.4%
|
→ +3% | Estable |
| 04 | iPad Pro 12.9" | Tablets | 274 | $164,124 |
11.4%
|
↑ +8% | Top |
| 05 | Samsung 55" QLED | TV / Video | 187 | $130,715 |
9.1%
|
↓ -5% | Revisar |