🛒 Market Basket Analysis: Inteligencia Comercial a través de los Datos
- Hugo de Val
- 17 abr
- 7 Min. de lectura
Actualizado: 18 abr
El análisis de las cestas de compra es una técnica de análisis de datos que ayuda a las empresas a descubrir qué productos se compran juntos con frecuencia. Aunque se basa en conceptos estadísticos, en esta presentación lo explicamos de forma clara y accesible, sin necesidad de saber de programación ni matemáticas avanzadas.
🎯 ¿Qué busca el análisis de cesta de la compra?
Imagina que tienes una tienda física o un supermercado online. Notas que muchos clientes compran bananas y leche orgánica, o que cada vez que alguien compra cilantro fresco, también lleva limones. Pero... ¿cómo podrías saber esto con miles o millones de tickets de compra al mes?
Aquí entra en juego el Market Basket Analysis: una técnica que descubre automáticamente esos patrones ocultos entre los productos.
🧠 ¿Por qué es útil para tu negocio?
🛍️ Promociones cruzadas: "Si compras esto, te interesa esto otro."
🧠 Entender a tu cliente: sus hábitos, sus rutinas, sus preferencias.
🗺️ Optimizar la disposición en tienda o la navegación online.
📈 Aumentar el ticket medio recomendando productos relacionados.
🪄 ¿Cómo funciona, explicado con un ejemplo sencillo?
Imagina que tienes una tienda y registras estas cuatro compras:
Judías verdes, sopa de champiñones, cebolla frita
Pavo, judías verdes, cebolla frita
Judías verdes
Pavo
Al observar estos datos, notas que varias personas compran judías verdes con cebolla frita. El sistema detecta este patrón y lo convierte en una regla:
"Si alguien compra judías verdes, es bastante probable que también compre cebolla frita."
Esto no significa que una cause la otra, pero sí que aparecen juntas con frecuencia, y eso es valioso para tomar decisiones comerciales.
🧾 ¿Qué hicimos en este proyecto?
1. Analizamos millones de tickets de compra de un herbolario ecológico
Cada ticket nos dice qué productos se compraron juntos. Así, una cesta como esta:
Banana, cilantro, limones, leche orgánica...
...se transforma en una línea de datos para detectar patrones.
2. Agrupamos los productos de cada pedido
A partir de los tickets originales que indican qué productos se compraron en cada pedido, se agruparon los nombres de los productos por ID de pedido. Esto genera una "cesta de productos" por transacción, esencial para construir la matriz de análisis posterior. Cada cesta queda representada por una cadena separada por comas con los nombres de los productos comprados en conjunto.
Esta agrupación es fundamental porque el análisis de reglas de asociación no funciona sobre productos individuales aislados, sino sobre combinaciones de productos que ocurren en una misma transacción. Al transformar los datos a este formato, estamos preparando el terreno para calcular con qué frecuencia ocurren ciertas combinaciones y detectar patrones de coocurrencia entre artículos. de los tickets originales que indican qué productos se compraron en cada pedido, se agruparon los nombres de los productos por ID de pedido. Esto genera una "cesta de productos" por transacción, esencial para construir la matriz de análisis posterior. Cada cesta queda representada por una cadena separada por comas con los nombres de los productos comprados en conjunto.
df = pd.read_sql_query(text("SELECT * FROM tickets"), conexion)
df['fecha'] = pd.to_datetime(df['fecha'])
df_cesta = df[['id_pedido', 'nombre_producto']]
df_agrupado = df_cesta.groupby('id_pedido')['nombre_producto'].apply(lambda productos: ','.join(productos))
3. Creamos una gran tabla de presencia/ausencia
df_transacciones = df_agrupado.str.get_dummies(sep=',')
Cada fila representa un pedido, y cada columna un producto. Si el producto aparece en el pedido, el valor es 1, si no, es 0.
Ejemplo visual del resultado:
id_pedido | Banana | Cilantro Orgánico | Limones | Leche Orgánica | Fresas |
1001 | 1 | 1 | 1 | 0 | 0 |
1002 | 0 | 0 | 0 | 1 | 1 |
1003 | 1 | 0 | 1 | 1 | 0 |
1004 | 0 | 1 | 0 | 0 | 1 |
Esto permite a los algoritmos detectar cuántas veces aparecen productos juntos en la misma transacción, lo cual es la base para descubrir reglas de asociación útiles.
Cada fila representa un pedido, y cada columna un producto. Si el producto aparece en el pedido, el valor es 1, si no, es 0.
4. Calculamos el soporte de cada producto
soporte = df_transacciones.mean() * 100
soporte.sort_values(ascending=False)
Esto nos indica qué porcentaje de los pedidos contiene cada producto, es decir, la media de aparición del producto sobre el total de transacciones. En otras palabras, representa la frecuencia relativa de cada producto en el conjunto de compras analizado, expresado como porcentaje. Ejemplos:
Banana 23.8%
Bolsa de Bananas Orgánicas 19.1%
Fresas Orgánicas 13.3%
Espinacas Baby Orgánicas 12.1%
5. Calculamos las relaciones entre productos
Este bloque de código es crucial para el análisis: genera todas las combinaciones posibles de productos dentro del conjunto de transacciones, y calcula para cada par dos indicadores clave:
Confianza: nos dice cuán probable es que, si un cliente compra el producto A, también compre el producto B. Una confianza del 25% entre 'Cilantro → Limones' significa que 1 de cada 4 compradores de cilantro también lleva limones.
Lift: evalúa si esa relación ocurre más (o menos) de lo esperado por azar. Un lift mayor a 1 indica que los productos tienden a aparecer juntos con más frecuencia de la que se esperaría si fueran independientes. Cuanto más alto el lift, más fuerte y útil es la relación para estrategias de venta cruzada.
Estas métricas son fundamentales porque nos permiten detectar patrones significativos, evitando asociaciones triviales o irrelevantes.
from itertools import combinations
asociaciones = []
def confianza(antecedente, consecuente):
compras_a = df_transacciones[antecedente].sum()
compras_ab = len(df_transacciones[(df_transacciones[antecedente] == 1) & (df_transacciones[consecuente] == 1)])
return compras_ab / compras_a if compras_a > 0 else 0
def lift(antecedente, consecuente):
soporte_a = df_transacciones[antecedente].mean()
soporte_b = df_transacciones[consecuente].mean()
soporte_ab = len(df_transacciones[(df_transacciones[antecedente] == 1) & (df_transacciones[consecuente] == 1)]) / len(df_transacciones)
return soporte_ab / (soporte_a soporte_b) if soporte_a soporte_b > 0 else 0
for antecedente, consecuente in combinations(df_transacciones.columns, 2):
conf = confianza(antecedente, consecuente)
lft = lift(antecedente, consecuente)
asociaciones.append({
'antecedente': antecedente,
'consecuente': consecuente,
'confianza': round(conf * 100, 1),
'lift': round(lft, 2)
})
6. Filtramos sólo las relaciones más valiosas
Usamos la mediana de confianza (5.1%) como umbral para quedarnos solo con las reglas más significativas:
Rango de confianza: 0.0019 - 0.3018
Media: 0.0605
Mediana: 0.0512
Total de combinaciones analizadas: 780
Esto nos permitió establecer un criterio de corte realista: descartar relaciones con menos del 5% de confianza, quedándonos solo con las reglas que tienen una probabilidad destacable de repetirse en la práctica.
df_asociaciones = pd.DataFrame(asociaciones)
df_asociaciones = df_asociaciones[df_asociaciones['confianza'] > 0.0512]
Resultados estadísticos del conjunto de reglas antes del filtrado:
valores_confianza = [confianza(a, b) for a, b in combinations(df_transacciones.columns, 2)]
min_conf = min(valores_confianza)
max_conf = max(valores_confianza)
media_conf = np.mean(valores_confianza)
mediana_conf = np.median(valores_confianza)
print(f"Rango de confianza: {min_conf:.4f} - {max_conf:.4f}")
print(f"Media: {media_conf:.4f}")
print(f"Mediana: {mediana_conf:.4f}")
print(f"Total de combinaciones analizadas: {len(valores_confianza)}")
7. Enriquecimos cada producto con su categoría
Para que las reglas no sean solo pares de nombres de productos, agregamos información estructural a cada antecedente, como su ID, sección y departamento. Esto permite, por ejemplo:
- Clasificar reglas por categorías de producto (fruta, lácteos, panadería, etc.).
- Aplicar estrategias por zona o familia de productos.
- Visualizar relaciones agrupadas por secciones en dashboards o gráficas.
Esto se logra uniendo la tabla de asociaciones con una tabla única de productos extraída del dataset original.
```python
productos_unicos = df[['id_producto', 'id_seccion', 'id_departamento', 'nombre_producto']].drop_duplicates()
df_asociaciones_enriquecido = df_asociaciones.merge(productos_unicos, left_on='antecedente', right_on='nombre_producto', how='left')
df_asociaciones_enriquecido = df_asociaciones_enriquecido.drop(columns=['nombre_producto'])
Con este enriquecimiento, ya no solo sabremos que Aguacate Orgánico*se asocia a Banana, sino que además sabemos que ambos pertenecen a la sección 24 y al departamento 4, lo que permite análisis más profundos y acciones más dirigidas.`
📊 ¿Qué descubrimos?
🔝 Principales relaciones encontradas (extracto real franja superior e inferior)
Producto inicial | Producto asociado | Confianza (%) | Lift | Sección | Departamento |
Cilantro orgánico | Limones | 25.4 | 3.6 | 16 | 4 |
Cebolla roja orgánica | Cilantro orgánico | 12.8 | 3.6 | 83 | 4 |
Ajo orgánico | Cebolla amarilla orgánica | 20.1 | 3.5 | 83 | 4 |
Apio orgánico en ramillete pequeño | Zanahorias | 12.0 | 3.3 | 83 | 4 |
Apio orgánico en ramillete pequeño | Pepino orgánico | 12.7 | 3.1 | 83 | 4 |
Frambuesas orgánicas | Fresas orgánicas | 24.9 | 1.9 | 123 | 4 |
Aguacate orgánico | Bolsa de bananas orgánicas | 13.0 | 0.7 | 24 | 4 |
Aguacate Hass orgánico | Banana | 14.6 | 0.6 | 24 | 4 |
> 🔍 Estas reglas son muy útiles para establecer relaciones de producto en tienda, promociones cruzadas, e incluso recomendaciones personalizadas en plataformas de e-commerce.
✅ Conclusión: ¿Cómo puedes aprovechar esto en tu negocio?
El análisis de cestas de la compra no es solo una herramienta estadística, sino una forma de comprender mejor cómo compran tus clientes y cómo mejorar tus ventas de manera estratégica.
🔍 ¿Qué significan realmente confianza y lift?
- Confianza es la probabilidad de que un cliente compre un producto B si ya compró el producto A. Por ejemplo, una confianza del 25% entre Cilantro Orgánico → Limones nos dice que 1 de cada 4 personas que compra cilantro también compra limones. Esta métrica permite establecer reglas de recomendación que tienen una probabilidad real de repetirse.
- Lift mide la fuerza de esa asociación comparada con el azar. Si el lift es mayor que 1, la relación entre productos es más fuerte de lo que cabría esperar si las compras fueran independientes. Por ejemplo, un lift de 3.6 significa que la probabilidad de que los dos productos se compren juntos es 3.6 veces mayor que por azar.
🎯 Aplicaciones comerciales del modelo
- 🛒 Venta cruzada (cross-selling): puedes sugerir productos complementarios en tienda física, e-commerce o apps de entrega. Si alguien pone cilantro en el carrito, puedes recomendarle limones automáticamente.
- 📢 Promociones combinadas: puedes crear packs o descuentos que agrupen productos con alto lift, porque sabes que los clientes ya tienden a comprarlos juntos.
- 🗺️ Optimización del layout: puedes colocar físicamente los productos cerca unos de otros, facilitando la experiencia del cliente y aumentando la conversión.
- 📦 Gestión de inventario inteligente: si sabes que dos productos se compran juntos, puedes coordinar su reabastecimiento y evitar faltantes o excesos.
Esta técnica te permite pasar de los datos a decisiones concretas: no se trata de contar ventas, sino de entender cómo piensan tus clientes cuando compran. Es transformar un historial de tickets en una estrategia comercial.
Comments