Segmentación de Clientes para Tienda de Ropa “TrendyStyles”

¡Descubre los secretos de tus clientes con clustering avanzado! 👗🛍️

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.

📊 Descripción de la Base de Datos

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)

🎯 Objetivos de la Sesión

  1. Aprender a preparar datos mixtos para clustering con clustMD.

  2. Aplicar el modelo EII para segmentación.

  3. Identificar 4 perfiles de clientes y sus características clave.

  4. 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

2. Preparación de Datos para clustMD

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" ...

3. Clustering con clustMD

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>

Interpretación de los Clusters Identificados

Segmento 1: “Mayores Conservadores”

  • 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

Segmento 2: “Adultos Tradicionales”

  • 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

Segmento 3: “Jóvenes Activos”

  • 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”)

Segmento 4: “Jóvenes Ocasionales”

  • 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

📊 Conclusiones Clave

  1. 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.

  2. Oportunidades:

    • Aumentar frecuencia en Segmentos 1 y 2 (mayor gasto potencial)

    • Mejorar satisfacción en Segmento 4 (futura lealtad)