Eres el Gerente de Marketing de “TrendyStyles”, una tienda de ropa que quiere lanzar campañas personalizadas. Tienes datos de 200 clientes con información mixta (numérica, ordinal y nominal).
¡Tu misión! 🔍 Usar la función
clustMD
para encontrar 4 segmentos
naturales de clientes y diseñar estrategias de marketing a
su medida.
Variable | Tipo | Descripción | Escala/Rango |
---|---|---|---|
Edad | Continua | Edad del cliente | 18-65 años |
Gasto_Mensual | Continua | Gasto promedio mensual (USD) | $50-$500 |
Frecuencia | Ordinal | Visitas al mes | 1 (Baja), 2 (Media), 3 (Alta) |
Estilo_Preferido | Nominal | Preferencia de estilo de ropa | Casual, Deportivo, Elegante, Boho |
Satisfacción | Ordinal | Nivel de satisfacción (1-5) | 1 (Muy insatisfecho) - 5 (Muy satisfecho) |
Aprender a preparar datos mixtos para clustering
con clustMD
.
Aplicar el modelo EII para segmentación.
Identificar 4 perfiles de clientes y sus características clave.
Generar estrategias de marketing personalizadas por segmento.
# install.packages("clustMD") # Descomentar si es necesario
library(clustMD) # Para clustering mixto
## Warning: package 'clustMD' was built under R version 4.4.3
##
##
## __ __ __ ________
## ______/ /_ ________ / /_ / \/ / __ \
## / ____/ / / / / ____// __// /\_/ / / / /
## / /___/ / /_/ /\___ // /__/ / / / /__/ /
## \____/_/\____//____//____/_/ /_/______/ version 1.2.1
##
##
library(ggplot2) # Para gráficos bonitos
## Warning: package 'ggplot2' was built under R version 4.4.3
library(dplyr) # Para manipulación de datos
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(kableExtra) # Para tablas elegantes
## Warning: package 'kableExtra' was built under R version 4.4.3
##
## Adjuntando el paquete: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
Cargar base de datos
datos_ropa=read.csv("TrendyStyles.csv")
head(datos_ropa)
## Edad Gasto_Mensual Frecuencia Estilo_Preferido Satisfacción
## 1 23 78 2 Casual 2
## 2 24 103 2 Deportivo 2
## 3 27 108 2 Deportivo 3
## 4 24 92 2 Casual 3
## 5 16 102 1 Casual 2
## 6 23 72 1 Deportivo 3
library(clustMD)
# Convertimos a matriz en el orden CORRECTO: Continuas -> Ordinales -> Nominales
Y <- as.matrix(datos_ropa %>%
mutate(
# Las variables ordinales deben ser transformadas a Factor y luego a numérico
# para asegurar que los valores se mapeen a 1, 2, 3...
Frecuencia = as.numeric(factor(Frecuencia, levels = sort(unique(datos_ropa$Frecuencia)))),
Satisfacción = as.numeric(factor(Satisfacción, levels = sort(unique(datos_ropa$Satisfacción)))),
# Estilo_Preferido es nominal, transformarla a numérico para clustMD
Estilo_num = as.numeric(factor(Estilo_Preferido, levels = c("Casual", "Deportivo", "Elegante")))
) %>%
select(Edad, Gasto_Mensual, Frecuencia, Satisfacción, Estilo_num))
# Estandarizamos SOLO las continuas (columnas 1-2)
Y_scaled_continuous <- scale(Y[, 1:2])
Y_categ <- Y[, 3:5] # Variables categóricas
# Aseguramos que las categóricas (ordinales y nominales) empiecen en 1
# Esto ya debería estar cubierto por la transformación a factor y as.numeric si los niveles son 1,2,3...
# pero esta sigue siendo una buena práctica de seguridad para cualquier valor que no sea secuencial desde 1.
Y_categ <- apply(Y_categ, 2, function(x) x - min(x) + 1)
# Unimos de nuevo para formar la matriz final para clustMD
Y <- cbind(Y_scaled_continuous, Y_categ)
head(Y)
## Edad Gasto_Mensual Frecuencia Satisfacción Estilo_num
## [1,] -1.0212541 -1.350505 2 2 1
## [2,] -0.9457548 -1.172891 2 2 2
## [3,] -0.7192568 -1.137368 2 3 2
## [4,] -0.9457548 -1.251041 2 3 1
## [5,] -1.5497493 -1.179996 1 2 1
## [6,] -1.0212541 -1.393132 1 3 2
str(Y) # Verificar la estructura final de Y
## num [1:300, 1:5] -1.021 -0.946 -0.719 -0.946 -1.55 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:5] "Edad" "Gasto_Mensual" "Frecuencia" "Satisfacción" ...
set.seed(123)
resultado <- clustMD(
X = Y, # Matriz de datos de entrada.
G = 4, # Número deseado de clusters a encontrar.
CnsIndx = 2, # Cantidad de variables continuas (las primeras columnas de X).
OrdIndx = 2, # Cantidad de variables ordinales (después de las continuas).
Nnorms = 100000, # Número de muestras Monte Carlo para estimaciones de categóricas.
MaxIter = 300, # Número máximo de iteraciones del algoritmo EM.
model = "EII", #Modelo de covarianza para variables continuas (esférico, igual varianza por cluster).
startCL = "kmeans", # Método de inicialización de clusters ("kmeans" para datos mixtos).
autoStop = TRUE, # Detener el algoritmo automáticamente cuando converge.
stop.tol = 0.0001, # Tolerancia para la convergencia (cambio en la log-verosimilitud).
ma.band = 30, # Ventana para el promedio móvil en la comprobación de convergencia.
store.params = FALSE #No almacenar los parámetros del modelo en cada iteración para ahorrar memoria.
)
## | | | 0% | |======= | 10% | |============== | 20% | |======================================================================| 100%
# Verificamos los clusters
table(resultado$cl)
##
## 1 2 3 4
## 69 81 70 80
Ahora interpretaremos a los cluster obtenidos, primero unos pasos previos:
library(dplyr) # Necesitamos dplyr para trabajar con los datos de forma fácil
# --- Parte 1: Una pequeña función que calcula la "moda" ---
# La moda es el valor que más se repite. R no tiene una función sencilla para esto,
# así que la creamos una vez y la usamos cuando la necesitemos.
get_mode <- function(x) {
if (length(x) == 0) return(NA) # Si el grupo está vacío, no hay moda
unique_values <- unique(x) # Encontramos todos los valores únicos
# Contamos cuántas veces aparece cada valor y elegimos el que aparece más
unique_values[which.max(tabulate(match(x, unique_values)))]
}
# --- Parte 2: Preparamos los datos para el resumen ---
# Asignación final
datos_ropa$Segmento <- resultado$cl
table(datos_ropa$Segmento) # Verificamos que sean 4 clusters
##
## 1 2 3 4
## 69 81 70 80
# --- Parte 3: Creamos el cuadro resumen ---
# Usamos 'dplyr' para agrupar y calcular las características de cada cluster
resumen_clientes_por_segmento <- datos_ropa %>%
group_by(Segmento) %>% # Agrupamos los datos por cada 'Segmento' (cluster)
summarize(
'Nº Clientes' = n(), # Calculamos cuántos clientes hay en cada segmento
'Edad Media' = mean(Edad, na.rm = TRUE), # Calculamos la edad promedio para cada segmento
'Gasto Mensual Medio' = mean(Gasto_Mensual, na.rm = TRUE), # Calculamos el gasto promedio
'Frecuencia (Moda)' = get_mode(Frecuencia), # Encontramos la frecuencia de compra más común
'Estilo Preferido (Moda)' = get_mode(Estilo_Preferido), # Encontramos el estilo preferido más común
'Satisfacción (Moda)' = get_mode(Satisfacción) # Encontramos el nivel de satisfacción más común
) %>%
ungroup() # Una vez que terminamos de agrupar, quitamos la agrupación
# --- Parte 4: Mostramos el cuadro resumen ---
# Esto imprimirá la tabla en la consola
print(resumen_clientes_por_segmento)
## # A tibble: 4 × 7
## Segmento `Nº Clientes` `Edad Media` `Gasto Mensual Medio` `Frecuencia (Moda)`
## <dbl> <int> <dbl> <dbl> <int>
## 1 1 69 56.0 441. 1
## 2 2 81 39.5 355. 1
## 3 3 70 30.4 197. 3
## 4 4 80 22.0 93.4 2
## # ℹ 2 more variables: `Estilo Preferido (Moda)` <chr>,
## # `Satisfacción (Moda)` <int>
Perfil:
69 clientes (25% del total)
Edad avanzada (56 años en promedio)
Mayor gasto mensual ($440) pero baja frecuencia de compra (moda = 1)
Prefieren estilo Casual
Satisfacción media-alta (moda = 4)
🔍 Insights:
Clientes mayores que realizan compras menos frecuentes pero de mayor
valor. Su estilo casual y alta satisfacción sugieren lealtad a la
marca.
📌 Estrategia recomendada:
Programas de fidelización para aumentar frecuencia (ej: “Compra 3 veces en 3 meses y recibe un descuento”)
Ofertas en paquetes premium (maximizar valor por transacción)
Comunicación tradicional (email, teléfono) en lugar de redes sociales
Perfil:
81 clientes (29% del total)
Edad adulta (40 años en promedio)
Gasto medio ($355) con baja frecuencia (moda = 1)
Prefieren estilo Elegante
Satisfacción media (moda = 3)
🔍 Insights:
Clientes con poder adquisitivo que valoran elegancia, pero con menor
engagement. Satisfacción neutral indica oportunidades de
mejora.
📌 Estrategia recomendada:
Eventos exclusivos de lanzamiento de colecciones elegantes
Encuestas de satisfacción para identificar puntos de mejora
Descuentos por compras recurrentes para aumentar frecuencia
Perfil:
70 clientes (25% del total)
Más jóvenes (30 años en promedio)
Gasto medio-bajo ($197) pero alta frecuencia (moda = 3)
Prefieren estilo Deportivo
Satisfacción alta (moda = 4)
🔍 Insights:
Clientes jóvenes, muy activos y satisfechos. Compran con frecuencia pero
en montos menores.
📌 Estrategia recomendada:
Membresía con beneficios por frecuencia (ej: “Club del Comprador Frecuente”)
Promociones en redes sociales (TikTok, Instagram)
Bundles de productos deportivos (ej: “2 polos + 1 short por $99”)
Perfil:
80 clientes (29% del total)
Más jóvenes (22 años en promedio)
Menor gasto mensual ($93) y frecuencia media (moda = 2)
Prefieren estilo Casual
Satisfacción media-baja (moda = 3)
🔍 Insights:
Clientes jóvenes con bajo poder adquisitivo. Satisfacción más baja
sugiere problemas en experiencia de compra o expectativas no
cumplidas.
📌 Estrategia recomendada:
Ofertas de entrada (ej: “Primera compra con 20% de descuento”)
Mejorar experiencia en tienda/online (rapidez, atención)
Promociones en universidades o centros juveniles
Relación Edad-Gasto:
A mayor edad, mayor gasto por transacción pero menor frecuencia.
Los jóvenes compran más seguido pero en montos menores.
Oportunidades:
Aumentar frecuencia en Segmentos 1 y 2 (mayor gasto potencial)
Mejorar satisfacción en Segmento 4 (futura lealtad)