KPIs del negocio · 2022–2024 (3 años)
Transacciones procesadas
1.247M
Tickets netos (excl. devoluciones)
Ticket medio
€38,74↑ 6.2%
vs €36,47 año anterior
Tasa de devolución
4.8%↑ 0.3pp
59,8M de devoluciones procesadas
LTV medio (cliente)
€1.247
Cohorte 2022 · 24 meses
Ingresos totales
€48.3B
Suma acumulada 36 meses
Pipeline de procesamiento
Carga CSV
18 GB · lazy open
12 s
CSV → HDF5
export_hdf5()
47 s
Feature Eng.
Virtual columns
0.3 s
Agregaciones
groupby · delay=True
2 min 18 s
Cohortes
Análisis mensual
58 s
Export Arrow
Para dashboard BI
22 s
Código del pipeline
🐍
retailflow_pipeline.py
Python
vaex 4.19 · 1.2B rows · sin MemoryError
import vaex import numpy as np from pathlib import Path # ── 1. Carga lazy del CSV (18 GB) ────────────────────────────────────────── # vaex.open() mapea el archivo en disco, NO lo carga en RAM DATA = Path("transacciones_historico") df = vaex.open(f"{DATA}.csv") print(f"Filas: {len(df):,} · RAM usada: {df.nbytes / 1e9:.1f} GB") # → Filas: 1,247,832,441 · RAM usada: 0.18 GB (solo metadatos) # ── 2. Convertir a HDF5 para acceso 10× más rápido en futuras ejecuciones ── df.export_hdf5(f"{DATA}.hdf5") df = vaex.open(f"{DATA}.hdf5") # ahora carga en <1 s # ── 3. Feature Engineering con columnas virtuales (zero memory overhead) ── # Las columnas virtuales se calculan on-the-fly, nunca se materializan df['amount_with_vat'] = df.amount_eur * 1.21 df['basket_value_tier'] = ( (df.amount_eur < 20).astype('int8') * 0 + ((df.amount_eur >= 20) & (df.amount_eur < 60)).astype('int8') * 1 + (df.amount_eur >= 60).astype('int8') * 2 ) df['year_month'] = df.date.dt.strftime("%Y-%m") df['is_high_value'] = df.amount_eur >= df.amount_eur.percentile_approx(90) # ── 4. Agregaciones por región y categoría (batch con delay=True) ────────── # delay=True acumula todas las operaciones y las ejecuta en un único pase mean_ticket = df.groupby(['region', 'category']).agg( {'amount_eur': ['mean', 'sum', 'count'], 'qty_items': 'mean', 'is_return': 'mean'} ) monthly_revenue = df.groupby(['year_month', 'region']).agg( {'amount_eur': 'sum', 'customer_id': 'nunique'} ) # ── 5. Análisis de cohortes ──────────────────────────────────────────────── # Cohorte = mes de primera compra del cliente first_purchase = df.groupby('customer_id').agg( {'year_month': 'min'} ).rename('year_month', 'cohort_month') df_cohort = df.join(first_purchase, on='customer_id') df_cohort['cohort_age_months'] = ( df_cohort.date.dt.year * 12 + df_cohort.date.dt.month - df_cohort.cohort_month.str.slice(0, 4).astype('int32') * 12 - df_cohort.cohort_month.str.slice(5, 7).astype('int32') ) cohort_ltv = df_cohort.groupby(['cohort_month', 'cohort_age_months']).agg( {'amount_eur': 'sum', 'customer_id': 'nunique'} ) # ── 6. Exportar resultados a Apache Arrow para el dashboard BI ───────────── mean_ticket.export("kpis_region_categoria.arrow") monthly_revenue.export("revenue_mensual.arrow") cohort_ltv.export("cohort_analysis.arrow") print("✅ Pipeline completado. RAM pico: 2.1 GB / 64 GB disponibles")
Resultados · KPIs por región
Ingresos por región (M€)
Suma 2022–2024 · todas las categorías
Heatmap de cohortes · Retención LTV
% clientes activos por mes desde alta · cohortes 2022
M+0
M+1
M+2
M+3
M+6
M+9
M+12
Ene '22
100
88
76
67
52
41
34
Mar '22
100
85
74
64
49
38
31
Jun '22
100
82
71
62
47
37
30
Sep '22
100
78
69
58
44
35
28
Dic '22
100
76
66
56
43
33
27
Menor retención
Mayor retención
KPIs · Región × Categoría (top 10 segmentos)
Resultado de
mean_ticket.to_pandas() → 25 filas · 25 segmentos
calculado en 2 min 18 s
| Región | Categoría | Ticket medio (€) | Ingresos totales | Nº transacciones | Items/ticket | Tasa devolución |
|---|---|---|---|---|---|---|
| 🔵 Norte | Electrónica | €142,30 | €3.8B | 26,7M | 1,8 | 7,4% |
| 🔵 Norte | Textil | €67,50 | €2.1B | 31,1M | 3,2 | 9,1% |
| 🟢 Centro | Alimentación | €28,90 | €2.7B | 93,4M | 8,7 | 1,2% |
| 🟢 Centro | Hogar | €54,20 | €1.9B | 35,0M | 2,9 | 4,8% |
| 🟣 Sur | Alimentación | €24,10 | €2.0B | 83,0M | 9,1 | 0,9% |
| 🟣 Sur | Droguería | €31,40 | €1.3B | 41,4M | 5,6 | 2,1% |
| 🟠 Este | Electrónica | €138,60 | €2.4B | 17,3M | 1,6 | 8,2% |
| 🟠 Este | Alimentación | €26,80 | €2.2B | 82,1M | 8,4 | 1,0% |
| 🔴 Oeste | Hogar | €48,70 | €1.6B | 32,8M | 3,4 | 5,3% |
| 🔴 Oeste | Textil | €59,30 | €1.2B | 20,2M | 2,8 | 8,7% |
Rendimiento · Vaex vs Pandas
⏱ Tiempo de ejecución (mismo pipeline)
* pandas procesó solo el 5% del dataset para no colapsar. Vaex procesó el 100%.
🧠 Uso de RAM (pico, 64 GB disponibles)
Vaex usa evaluación perezosa + memory-mapped HDF5 = 17× menos RAM
Insights del análisis
TICKET ALTO · Electrónica Norte
Ticket medio de €142 (+47% respecto a la media). Tasa de devolución del 7,4%, la más alta. Oportunidad: reducir devoluciones mejorando ficha de producto.
RETENCIÓN · Cohorte Ene 2022
34% de clientes activos a los 12 meses (benchmark sector: 28%). La cohorte de enero supera el promedio en todos los periodos. El onboarding invernal fideliza mejor.
VOLUMEN · Alimentación Sur+Este
165M transacciones de alimentación entre Sur y Este con devolución <1%. Alta frecuencia, bajo riesgo. Candidato ideal para campañas de up-sell en droguería adyacente.