Segmetación de Clientes

Author

Erick Elí Gonzales Serrano

Published

December 26, 2024

Análisis de segmetación de clientes

Toda empresa que quiera ser competitiva dentro de su nicho de mercado debe considerar realizar una segmentación de sus clientes. Para el presente caso, se pretende realizar para un cojunto de clientes de una finaciera con la finalidad de personalizar productos, optimizar estrategias de marketing, mejorar la satisfacción del cliente y gestionar riesgos de manera más efectiva, maximizando la rentabilidad y fidelización en un mercado competitivo. En resumen, conocer de mejor manera el perfil de nuestra cartera de clientes.

Se va a optar por dos algoritmos de agrupamiento, los cuales serán comparados.

  • K-means: Algoritmo de agrupamiento no supervisado que divide un conjunto de datos en un número predefinido de clústeres (K).

  • Clustering Aglomerativo: Algoritmo de agrupamiento jerárquico que construye una jerarquía de clústeres mediante una serie de fusiones de grupos más pequeños.

OJO:

Aprendizaje No Supervisado: No se utilizan etiquetas o respuestas conocidas; el algoritmo encuentra patrones inherentes en los datos. Objetivo: Maximizar la similitud intra-cluster y minimizar la similitud inter-cluster.

1. Preprocemiento de los datos

1.1 Cargar datos y limpiar valores desconocidos

BD <- read.csv("Clientes.csv", fileEncoding = "latin1", header = TRUE) %>%
  select(-c(ClienteID, Nombre,SucursalID,UbigeoID)) %>% 
  filter(Género != "Otro")

1.2 Factorización con asignación de niveles

BD$Género <- factor(BD$Género,levels = c("Masculino", "Femenino"),labels = c("Masculino", "Femenino"))

BD$EstadoCivil <- factor(BD$EstadoCivil,levels = c("Soltero","Casado","Divorciado","Viudo"),labels = c("Soltero","Casado","Divorciado","Viudo"))

BD$NivelEducacion <- factor(BD$NivelEducacion,levels = c("Terciaria","Primaria","Secundaria","Universitaria"),labels = c("Terciaria","Primaria","Secundaria","Universitaria"))

BD$Empleo <- factor(BD$Empleo, levels = c("Empleado","Desempleado","Otro"),labels = c("Empleado","Desempleado","Otro"))

BD$TipoContrato <- factor(BD$TipoContrato, levels = c("Freelance","Permanente","Temporal"),labels = c("Freelance","Permanente","Temporal"))

BD$Salud <- factor(BD$Salud,levels = c("Regular","Buena","Mala"),labels = c("Regular","Buena","Mala"))

BD$ViviendaPropia <- factor(BD$ViviendaPropia, levels = c("False", "True"), labels = c("No", "Sí"))

BD$CondicionVulnerable <- factor(BD$CondicionVulnerable,levels = c("False", "True"),labels = c("No vulnerable", "Sí vulnerable"))

BD$HistorialCrediticio <- factor(BD$HistorialCrediticio,levels = c("Malo","Regular","Bueno"),labels = c("Malo","Regular","Bueno"))

1.3 Base de datos procesada para los algoritmos

BD_clust <- BD

1.3 One Hot Encoding

categorical_vars <- c("Género","EstadoCivil", "NivelEducacion", "Empleo", "TipoContrato", "Salud","ViviendaPropia","HistorialCrediticio","CondicionVulnerable")
BD_encoded <- model.matrix(~ Género + EstadoCivil + NivelEducacion + Empleo + TipoContrato + Salud + ViviendaPropia + HistorialCrediticio + CondicionVulnerable - 1, data = BD_clust)

BD_clust <- BD_clust[, !(names(BD_clust) %in% categorical_vars)]
BD_clust <- cbind(BD_clust, BD_encoded)

1.3 Estandarización de variables

BD_clust$Edad <- scale(BD_clust$Edad)[, 1] 
BD_clust$IngresosMensuales <- scale(BD_clust$IngresosMensuales)[, 1]
BD_clust$DeudasActivas <- scale(BD_clust$DeudasActivas)[, 1] 
BD_clust$SituacionFamiliar <- scale(BD_clust$SituacionFamiliar)[, 1]

1.4 Reducción de dimensionalidad

Se va utilizar la técnica del PCA (Análisis de Componentes Principales), la cual es una técnica de reducción de dimensionalidad que transforma el conjunto de datos a un nuevo espacio de menor dimensión, manteniendo la mayor parte de la varianza de los datos.

# Realizar PCA
pca_result <- prcomp(BD_clust, scale. = TRUE)

# Extraer los resultados del summary
pca_summary <- summary(pca_result)

# Crear una tabla con la varianza explicada y la varianza acumulada
variance_explained <- data.frame(
  Component = paste("PC", 1:ncol(pca_summary$importance), sep = ""), Variance_Explained = pca_summary$importance[2, ], Cumulative_Variance = pca_summary$importance[3, ])

# Mostrar la tabla con knitr::kable para mayor elegancia
kable(variance_explained, 
      caption = "Varianza Explicada por Componentes Principales (PCA)", col.names = c("Componente", "Varianza Explicada", "Varianza Acumulada"))
Varianza Explicada por Componentes Principales (PCA)
Componente Varianza Explicada Varianza Acumulada
PC1 PC1 0.09166 0.09166
PC2 PC2 0.08224 0.17390
PC3 PC3 0.08166 0.25556
PC4 PC4 0.06438 0.31994
PC5 PC5 0.06378 0.38372
PC6 PC6 0.06186 0.44558
PC7 PC7 0.06066 0.50624
PC8 PC8 0.05708 0.56332
PC9 PC9 0.04968 0.61299
PC10 PC10 0.04863 0.66163
PC11 PC11 0.04653 0.70816
PC12 PC12 0.04568 0.75385
PC13 PC13 0.04524 0.79909
PC14 PC14 0.04384 0.84293
PC15 PC15 0.04155 0.88447
PC16 PC16 0.03420 0.91867
PC17 PC17 0.02680 0.94547
PC18 PC18 0.02545 0.97091
PC19 PC19 0.01756 0.98847
PC20 PC20 0.00932 0.99780
PC21 PC21 0.00220 1.00000
PC22 PC22 0.00000 1.00000

1.4.1 Visualización del PCA

screeplot(pca_result, type = "lines", main = "Scree Plot de PCA")

1.4.2 Elección del número de componentes

datos_pca <- pca_result$x[, 1:10]

2. Clustering Aglomerativo

2.1 Cálculo de la Matriz de Distancias entre las observaciones

# Matriz de distancias Euclídea
dist_matrix <- dist(datos_pca, method = "euclidean")

2.2 Aplicación del Algoritmo Aglomerativo

Usamos la función hclust() para crear el dendrograma con diferentes métodos de enlace.

# Clustering aglomerativo con Complete Linkage
hc_complete <- hclust(dist_matrix, method = "complete")
# Dendrograma básico con enlace completo
plot(hc_complete, main = "Dendrograma - Complete Linkage")

2.3 Definición del número de clústers y agregar a la base original

# Corte del dendrograma aglomerativo en 5 clusters
clusters_aglomerativo <- cutree(hc_complete, k = 5)

# Añadimos las asignaciones al dataset original
BD$cluster_hc <- as.factor(clusters_aglomerativo)

3. K - means

3.1 Observamos el comportamieto de WSS para disitntos clústers

# Aplicar K-means 
set.seed(123)  # Para reproducibilidad
wss <- sapply(1:10, function(k) {  # Probar con k = 1 hasta 10 clusters
  kmeans(datos_pca, centers = k, nstart = 25)$tot.withinss})

# Graficar el WSS (Within Sum of Squares) para cada número de clusters
plot(1:10, wss, type = "b", pch = 19, frame = FALSE, xlab = "Número de Clusters", ylab = "WSS")

3.2 Definición del número de clústers y agregar a la base original

# Aplicar K-means con 5 clusters
kmeans_result <- kmeans(datos_pca, centers = 5, nstart = 25)
# Añadir los clusters a los datos
datos_pca <- cbind(datos_pca, cluster = kmeans_result$cluster)

ggplot(datos_pca, aes(x = PC1, y = PC2, color = as.factor(cluster))) +
  geom_point() +
  labs(title = "Segmentación de clientes - K-Means (5 clusters)", x = "Componente Principal 1", y = "Componente Principal 2") +
  scale_color_discrete(name = "Cluster") +
  theme_minimal()

# Añadir el cluster asignado a la base de datos original
BD$Cluster <- as.factor(kmeans_result$cluster)

4. Comparación de algoritmos

4.1 Observaciones por clúster

cluster_kmeans <- as.data.frame(table(BD$Cluster))
colnames(cluster_kmeans) <- c("Cluster", "Frecuencia_Kmeans")

cluster_hc <- as.data.frame(table(BD$cluster_hc))
colnames(cluster_hc) <- c("Cluster", "Frecuencia_HC")

combined_clusters <- merge(cluster_kmeans, cluster_hc, by = "Cluster", all = TRUE)

kable(combined_clusters, caption = "Distribución de Clientes por Cluster (K-means y Clustering Aglomerativo)", col.names = c("Cluster", "Frecuencia K-means", "Frecuencia Clustering Aglomerativo"))
Distribución de Clientes por Cluster (K-means y Clustering Aglomerativo)
Cluster Frecuencia K-means Frecuencia Clustering Aglomerativo
1 1310 1316
2 2449 5323
3 2485 704
4 2403 1767
5 934 471

4.2 Distribución Salarial por clúster

4.2.1 K - means

p <- ggplot(BD, aes(x = as.factor(Cluster), y = IngresosMensuales)) + 
  geom_boxplot(fill = "lightblue", color = "darkblue") + 
  labs(title = "Distribución de Ingresos Mensuales por Cluster K-means",
       x = "Cluster K-means",
       y = "Ingresos Mensuales")

# Convertir a gráfico interactivo con plotly
ggplotly(p)

4.2.2 Clúster Aglomerativo

p <- ggplot(BD, aes(x = as.factor(cluster_hc), y = IngresosMensuales)) + 
  geom_boxplot(fill = "lightblue", color = "darkblue") + 
  labs(title = "Distribución de Ingresos Mensuales por Cluster Aglomerativo",
       x = "Cluster Aglomerativo",
       y = "Ingresos Mensuales")

# Convertir a gráfico interactivo con plotly
ggplotly(p)

4.3 Personas Vulnerables por Cluster

BD_vulnerables <- BD %>% filter(CondicionVulnerable == "Sí vulnerable")

cluster_kmeans <- as.data.frame(table(BD_vulnerables$Cluster))
colnames(cluster_kmeans) <- c("Cluster", "Frecuencia_Kmeans")

cluster_hc <- as.data.frame(table(BD_vulnerables$cluster_hc))
colnames(cluster_hc) <- c("Cluster", "Frecuencia_HC")

total_kmeans <- sum(cluster_kmeans$Frecuencia_Kmeans)
total_hc <- sum(cluster_hc$Frecuencia_HC)

cluster_kmeans$Porcentaje_Kmeans <- (cluster_kmeans$Frecuencia_Kmeans / total_kmeans) * 100
cluster_hc$Porcentaje_HC <- (cluster_hc$Frecuencia_HC / total_hc) * 100

combined_clusters <- merge(cluster_kmeans[, c("Cluster", "Porcentaje_Kmeans")], cluster_hc[, c("Cluster", "Porcentaje_HC")], by = "Cluster", all = TRUE)

kable(combined_clusters, 
      caption = "Distribución de Personas Vulnerables por Cluster (K-means y Clustering Aglomerativo)",col.names = c("Cluster", "Porcentaje K-means", "Porcentaje Clustering Aglomerativo"))
Distribución de Personas Vulnerables por Cluster (K-means y Clustering Aglomerativo)
Cluster Porcentaje K-means Porcentaje Clustering Aglomerativo
1 90.2203857 90.289256
2 0.3443526 1.446281
3 0.6887052 1.652893
4 0.0000000 2.066116
5 8.7465565 4.545454

4.4 Personas Desempleadas por Cluster

BD_desempleado <- BD %>% filter(Empleo == "Desempleado")

cluster_kmeans <- as.data.frame(table(BD_desempleado$Cluster))
colnames(cluster_kmeans) <- c("Cluster", "Frecuencia_Kmeans")

cluster_hc <- as.data.frame(table(BD_desempleado$cluster_hc))
colnames(cluster_hc) <- c("Cluster", "Frecuencia_HC")

total_kmeans <- sum(cluster_kmeans$Frecuencia_Kmeans)
total_hc <- sum(cluster_hc$Frecuencia_HC)

cluster_kmeans$Porcentaje_Kmeans <- (cluster_kmeans$Frecuencia_Kmeans / total_kmeans) * 100
cluster_hc$Porcentaje_HC <- (cluster_hc$Frecuencia_HC / total_hc) * 100

combined_clusters <- merge(cluster_kmeans[, c("Cluster", "Porcentaje_Kmeans")], cluster_hc[, c("Cluster", "Porcentaje_HC")], by = "Cluster", all = TRUE)

kable(combined_clusters, 
      caption = "Distribución de Personas Desempleadas por Cluster (K-means y Clustering Aglomerativo)",col.names = c("Cluster", "Porcentaje K-means", "Porcentaje Clustering Aglomerativo"))
Distribución de Personas Desempleadas por Cluster (K-means y Clustering Aglomerativo)
Cluster Porcentaje K-means Porcentaje Clustering Aglomerativo
1 31.540470 32.114883
2 20.156658 57.284595
3 20.574413 5.483029
4 18.537859 0.000000
5 9.190601 5.117494

4.5 Personas con mala salud por Cluster

BD_salud <- BD %>% filter(Salud == "Mala")

cluster_kmeans <- as.data.frame(table(BD_salud$Cluster))
colnames(cluster_kmeans) <- c("Cluster", "Frecuencia_Kmeans")

cluster_hc <- as.data.frame(table(BD_salud$cluster_hc))
colnames(cluster_hc) <- c("Cluster", "Frecuencia_HC")

total_kmeans <- sum(cluster_kmeans$Frecuencia_Kmeans)
total_hc <- sum(cluster_hc$Frecuencia_HC)

cluster_kmeans$Porcentaje_Kmeans <- (cluster_kmeans$Frecuencia_Kmeans / total_kmeans) * 100
cluster_hc$Porcentaje_HC <- (cluster_hc$Frecuencia_HC / total_hc) * 100

combined_clusters <- merge(cluster_kmeans[, c("Cluster", "Porcentaje_Kmeans")], cluster_hc[, c("Cluster", "Porcentaje_HC")], by = "Cluster", all = TRUE)

kable(combined_clusters, 
      caption = "Distribución de Personas con mala salud por Cluster (K-means y Clustering Aglomerativo)",col.names = c("Cluster", "Porcentaje K-means", "Porcentaje Clustering Aglomerativo"))
Distribución de Personas con mala salud por Cluster (K-means y Clustering Aglomerativo)
Cluster Porcentaje K-means Porcentaje Clustering Aglomerativo
1 1.476793 11.9198312
2 0.000000 11.8143460
3 0.000000 70.6751055
4 0.000000 0.6329114
5 98.523207 4.9578059

4.6 Personas con historial crediticio malo

BD_historial <- BD %>% filter(HistorialCrediticio == "Malo")

cluster_kmeans <- as.data.frame(table(BD_historial$Cluster))
colnames(cluster_kmeans) <- c("Cluster", "Frecuencia_Kmeans")

cluster_hc <- as.data.frame(table(BD_historial$cluster_hc))
colnames(cluster_hc) <- c("Cluster", "Frecuencia_HC")

total_kmeans <- sum(cluster_kmeans$Frecuencia_Kmeans)
total_hc <- sum(cluster_hc$Frecuencia_HC)

cluster_kmeans$Porcentaje_Kmeans <- (cluster_kmeans$Frecuencia_Kmeans / total_kmeans) * 100
cluster_hc$Porcentaje_HC <- (cluster_hc$Frecuencia_HC / total_hc) * 100

combined_clusters <- merge(cluster_kmeans[, c("Cluster", "Porcentaje_Kmeans")], cluster_hc[, c("Cluster", "Porcentaje_HC")], by = "Cluster", all = TRUE)

kable(combined_clusters, 
      caption = "Distribución de Personas con historial crediticio malo por Cluster (K-means y Clustering Aglomerativo)",col.names = c("Cluster", "Porcentaje K-means", "Porcentaje Clustering Aglomerativo"))
Distribución de Personas con historial crediticio malo por Cluster (K-means y Clustering Aglomerativo)
Cluster Porcentaje K-means Porcentaje Clustering Aglomerativo
1 88.722555 87.824351
2 0.499002 2.095808
3 0.998004 2.395210
4 0.000000 2.994012
5 9.780439 4.690619

5. Resultados

5.1 Cluster 1:

  • Ingresos mensuales: Este grupo tiene la menor media de ingresos mensuales.

  • Clientes vulnerables: El 90% de los clientes en este clúster se encuentran en condición vulnerable.

  • Desempleo: El porcentaje de personas desempleadas es el mayor de todos los grupos.

  • Salud: Solo un 1.5% de los clientes presentan mala salud.

  • Historial crediticio: Un 80% de los clientes tiene un mal historial crediticio.

Medidas recomendadas:

  • Productos financieros accesibles: Ofrecer microcréditos o préstamos de bajo interés con opciones de pago flexibles, ajustados a las dificultades económicas de los clientes.

  • Asesoría financiera y educación: Implementar programas de educación financiera para ayudar a los clientes a mejorar su manejo de deudas y historial crediticio.

  • Refinanciamiento y reestructuración de deudas: Ayudar a los clientes a gestionar sus deudas existentes de manera más eficiente.

5.2 Cluster 2 y 3 (Similares en características):

  • Ingresos mensuales: Estos clústeres tienen la media de ingresos más alta entre todos los grupos.

  • Clientes vulnerables: Menos del 1% de los clientes en estos clústeres son vulnerables.

  • Desempleo: El porcentaje de personas desempleadas es del 20%, casi el doble que el grupo con menor porcentaje de desempleados.

  • Salud: No se presentan clientes con mala salud en estos grupos.

  • Historial crediticio: El porcentaje de clientes con mal historial crediticio es mínimo, si bien existe, no llega al 1%.

Medidas recomendadas:

  • Productos financieros premium: Ofrecer productos exclusivos como tarjetas de crédito, planes de ahorro de alto rendimiento, y seguros de salud adecuados para este perfil de clientes.

  • Beneficios de salud: Aunque no presentan mala salud, se pueden ofrecer beneficios preventivos o seguros de salud complementarios.

  • Asesoría de inversión: Dado su buen poder adquisitivo, se pueden ofrecer servicios de planificación financiera y asesoría en inversiones a largo plazo.

5.3 Cluster 4:

  • Ingresos mensuales: Este clúster tiene la mayor media de ingresos mensuales entre los grupos.

  • Clientes vulnerables: Este grupo no tiene clientes vulnerables.

  • Desempleo: El porcentaje de personas desempleadas es bajo.

  • Salud: No tiene clientes con mala salud.

  • Historial crediticio: No tiene clientes con mal historial crediticio.

Medidas recomendadas:

  • Productos financieros avanzados: Ofrecer productos como fondos de inversión, seguros de vida, pensiones y planes de ahorro de alto rendimiento para satisfacer sus necesidades de inversión.

  • Servicios exclusivos: Crear un programa de clientes VIP con asesoría personalizada y productos exclusivos para clientes con buena salud y capacidad financiera.

  • Planes de inversión y jubilación: Brindar opciones para la planificación a largo plazo como pensiones privadas y otros instrumentos de inversión.

5.4 Cluster 5:

  • Ingresos mensuales: Este grupo tiene la media de ingresos mensuales por encima del clúster 1, pero debajo de los otros tres clústeres.

  • Clientes vulnerables: Es el segundo clúster con mayor número de clientes vulnerables (8% del total).

  • Desempleo: Tiene el menor porcentaje de desempleados de todos los grupos.

  • Salud: Tiene el mayor porcentaje de clientes con mala salud (98%).

  • Historial crediticio: Es el segundo grupo con mayor porcentaje de clientes con mal historial crediticio.

Medidas recomendadas:

  • Microcréditos y productos de bajo riesgo: Ofrecer créditos de bajo interés o sin interés para personas con condiciones de salud graves, con flexibilidad en el pago.

  • Seguro de salud y servicios médicos: Ofrecer seguros de salud accesibles y productos financieros que incluyan beneficios médicos o descuentos en consultas y tratamientos.

  • Educación financiera y reestructuración de deudas: Ayudar a mejorar el historial crediticio a través de programas de educación y asesoría financiera.

5.5 Conclusión:

Los clústeres presentan características y necesidades muy distintas, lo que permite a la empresa financiera implementar estrategias diferenciadas para cada uno:

  • Clústeres con menor poder adquisitivo y alta vulnerabilidad (Cluster 1 y 5): Se beneficiarían de productos financieros accesibles, programas de educación financiera, opciones de refinanciamiento de deudas y seguros de salud accesibles.

  • Clústeres con mayores ingresos y menos vulnerabilidad (Cluster 2, 3 y 4): Son más adecuados para productos financieros premium, servicios de inversión, seguros y asesoría personalizada.