El equipo de marketing de plazaVea desea entender mejor el perfil de sus clientes y optimizar sus campañas publicitarias. Para ello, cuenta con una base de datos de 200 clientes que incluye variables como frecuencia de compra, gasto promedio, preferencias de productos, y engagement con campañas digitales. Sin embargo, el alto número de variables dificulta la identificación de patrones claros.
Objetivos:
Reducir la dimensionalidad de los datos mediante PCA para identificar patrones ocultos.
Interpretar los componentes principales y su relación con las variables originales.
Segmentar clientes utilizando los componentes para estrategias de marketing personalizadas.
Variables (15):
Frecuencia_Compra: Número de compras mensuales.
Gasto_Promedio: Soles gastados por visita.
Edad: Rango de edad (18-25, 26-35, etc.).
Socio_Economico: Nivel socioeconómico (A, B, C, D).
Visita_Online: Frecuencia de visitas al sitio web/app (veces/semana).
Click_Ads: Porcentaje de clicks en anuncios digitales.
Redes_Sociales: Horas semanales en redes sociales.
Preferencia_Alimentos: Puntuación (1-10) de interés en alimentos.
Preferencia_Electro: Puntuación (1-10) de interés en electrónicos.
Lealtad_Marca: Puntuación (1-10) de lealtad a PlazaVea.
Satisfaccion_Atencion: Puntuación (1-10) de satisfacción con el servicio.
Metodo_Pago: Preferencia (Efectivo, Tarjeta, Digital).
Hora_Compra: Horario preferido (Mañana, Tarde, Noche).
Recibe_Ofertas: Frecuencia de apertura de emails promocionales.
Recomendacion: Probabilidad de recomendar PlazaVea (1-10).
library(readr)
data <- read_csv("plazavea_clientes.csv")
## Rows: 200 Columns: 12
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (12): Frecuencia_Compra, Gasto_Promedio, Visita_Online, Click_Ads, Tiemp...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
data_scaled <- scale(data) # Estandarizar (media=0, sd=1)
# Mostrar estadísticas descriptivas
cat("=== ESTADÍSTICAS DESCRIPTIVAS ===\n")
## === ESTADÍSTICAS DESCRIPTIVAS ===
summary(data)
## Frecuencia_Compra Gasto_Promedio Visita_Online Click_Ads
## Min. : 1.00 Min. : 41.0 Min. : 1.000 Min. :22.00
## 1st Qu.: 3.00 1st Qu.:101.8 1st Qu.: 7.000 1st Qu.:41.00
## Median : 5.00 Median :134.5 Median : 9.000 Median :50.00
## Mean : 5.43 Mean :134.0 Mean : 9.385 Mean :49.36
## 3rd Qu.: 8.00 3rd Qu.:170.0 3rd Qu.:12.000 3rd Qu.:58.00
## Max. :10.00 Max. :233.0 Max. :19.000 Max. :88.00
## Tiempo_Redes Satisfaccion Lealtad Edad
## Min. : 0.000 Min. : 3.00 Min. : 6.000 Min. :18.00
## 1st Qu.: 6.000 1st Qu.: 6.00 1st Qu.: 9.000 1st Qu.:27.00
## Median : 8.000 Median : 8.00 Median :10.000 Median :40.00
## Mean : 7.825 Mean : 7.55 Mean : 9.365 Mean :42.20
## 3rd Qu.:10.000 3rd Qu.: 9.00 3rd Qu.:10.000 3rd Qu.:56.25
## Max. :16.000 Max. :10.00 Max. :10.000 Max. :70.00
## Punt_Alimentos Punt_Electro Recibe_Ofertas Recomendacion
## Min. : 1.000 Min. : 1.000 Min. :15.00 Min. : 2.000
## 1st Qu.: 3.000 1st Qu.: 3.000 1st Qu.:36.00 1st Qu.: 6.000
## Median : 5.000 Median : 5.000 Median :44.00 Median : 7.000
## Mean : 5.405 Mean : 5.375 Mean :44.23 Mean : 6.675
## 3rd Qu.: 8.000 3rd Qu.: 8.000 3rd Qu.:52.00 3rd Qu.: 8.000
## Max. :10.000 Max. :10.000 Max. :74.00 Max. :10.000
cor_matrix <- cor(data_scaled)
print(cor_matrix) # Buscar correlaciones altas (>0.7)
## Frecuencia_Compra Gasto_Promedio Visita_Online Click_Ads
## Frecuencia_Compra 1.00000000 0.87485580 0.51571483 0.23922972
## Gasto_Promedio 0.87485580 1.00000000 0.40416301 0.17720996
## Visita_Online 0.51571483 0.40416301 1.00000000 0.60424681
## Click_Ads 0.23922972 0.17720996 0.60424681 1.00000000
## Tiempo_Redes 0.28342267 0.20671397 0.68346706 0.43795360
## Satisfaccion 0.51944146 0.48754751 0.30024055 0.16139667
## Lealtad 0.32726385 0.33108293 0.13306709 0.01138936
## Edad -0.04357140 -0.03330753 -0.08752056 -0.03111316
## Punt_Alimentos -0.03166010 0.02496166 -0.09207303 -0.14328391
## Punt_Electro 0.07308035 0.12191114 0.09566682 0.15821424
## Recibe_Ofertas 0.07589414 0.01180091 0.35284277 0.57609933
## Recomendacion 0.46398254 0.44870983 0.31744078 0.15033968
## Tiempo_Redes Satisfaccion Lealtad Edad
## Frecuencia_Compra 0.28342267 0.519441457 0.32726385 -0.04357140
## Gasto_Promedio 0.20671397 0.487547514 0.33108293 -0.03330753
## Visita_Online 0.68346706 0.300240549 0.13306709 -0.08752056
## Click_Ads 0.43795360 0.161396671 0.01138936 -0.03111316
## Tiempo_Redes 1.00000000 0.206938948 0.09241509 -0.12570380
## Satisfaccion 0.20693895 1.000000000 0.52947147 -0.06190061
## Lealtad 0.09241509 0.529471475 1.00000000 -0.07064546
## Edad -0.12570380 -0.061900614 -0.07064546 1.00000000
## Punt_Alimentos -0.07115861 -0.098583029 -0.07125087 0.05169384
## Punt_Electro -0.01597028 -0.051866378 -0.01785635 0.06365102
## Recibe_Ofertas 0.28997051 0.005981236 -0.05069019 -0.06366713
## Recomendacion 0.16546249 0.814441544 0.44519819 -0.08488746
## Punt_Alimentos Punt_Electro Recibe_Ofertas Recomendacion
## Frecuencia_Compra -0.03166010 0.073080351 0.075894143 0.463982540
## Gasto_Promedio 0.02496166 0.121911136 0.011800911 0.448709832
## Visita_Online -0.09207303 0.095666821 0.352842772 0.317440780
## Click_Ads -0.14328391 0.158214241 0.576099331 0.150339679
## Tiempo_Redes -0.07115861 -0.015970285 0.289970512 0.165462489
## Satisfaccion -0.09858303 -0.051866378 0.005981236 0.814441544
## Lealtad -0.07125087 -0.017856354 -0.050690191 0.445198187
## Edad 0.05169384 0.063651020 -0.063667131 -0.084887461
## Punt_Alimentos 1.00000000 -0.059338224 -0.023523511 -0.040308745
## Punt_Electro -0.05933822 1.000000000 0.074931685 0.007233196
## Recibe_Ofertas -0.02352351 0.074931685 1.000000000 -0.010183626
## Recomendacion -0.04030875 0.007233196 -0.010183626 1.000000000
Frecuencia_Compra
y
Gasto_Promedio
(0.875) → Correlación muy
fuerte
Satisfaccion
y
Recomendacion
(0.814) → Correlación muy
fuerte
Visita_Online
y
Tiempo_Redes
(0.683) → Correlación
fuerte
Visita_Online
y
Click_Ads
(0.604) → Correlación
fuerte
Click_Ads
y
Recibe_Ofertas
(0.576) → Correlación
fuerte
Estructura de correlaciones significativas:
Sí, es excelente candidato para PCA porque:
Presencia de multicolinealidad:
Variables con potencial redundancia:
Frecuencia_Compra
y
Gasto_Promedio
podrían combinarse en un
componente.
Satisfaccion
y
Recomendacion
claramente miden conceptos
relacionados.
Las variables de comportamiento digital
(Visita_Online
,
Click_Ads
,
Tiempo_Redes
) muestran patrones
correlacionados.
Punt_Alimentos
y
Punt_Electro
: Muestran correlaciones débiles con
la mayoría de las demás variables. Podrían no cargar fuertemente en
ningún componente.
Edad
: No correlaciona
significativamente con casi nada (-0.12 a 0.06).
Usaremos plotly
para crear un heatmap
interactivo:
# Instalar paquetes si es necesario
##install.packages(c("plotly", "reshape2"))
# Cargar librerías
library(plotly)
## Cargando paquete requerido: ggplot2
##
## Adjuntando el paquete: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(reshape2)
# Crear matriz de correlación (usando datos estandarizados)
cor_matrix <- cor(data_scaled)
# Convertir a formato largo para plotly
melted_cor <- melt(cor_matrix)
# Heatmap interactivo
plot_ly(
data = melted_cor,
x = ~Var1,
y = ~Var2,
z = ~value,
type = "heatmap",
colorscale = "RdYlBu",
reversescale = TRUE,
colorbar = list(title = "Correlación")
) %>%
layout(
title = "Matriz de Correlación Interactiva - PlazaVea",
xaxis = list(title = ""),
yaxis = list(title = ""),
margin = list(l = 100, r = 100, b = 100, t = 50)
)
Prueba de Bartlett: Antes del PCA, ejecuta:
library(psych)
##
## Adjuntando el paquete: 'psych'
## The following objects are masked from 'package:ggplot2':
##
## %+%, alpha
# Test de esfericidad de Bartlett - COMPLETO CON HIPÓTESIS
cat("\n=== TEST DE ESFERICIDAD DE BARTLETT ===\n")
##
## === TEST DE ESFERICIDAD DE BARTLETT ===
cat("HIPÓTESIS:\n")
## HIPÓTESIS:
cat("H0: La matriz de correlación es una matriz identidad (no hay correlaciones)\n")
## H0: La matriz de correlación es una matriz identidad (no hay correlaciones)
cat("H1: La matriz de correlación NO es una matriz identidad (existen correlaciones)\n\n")
## H1: La matriz de correlación NO es una matriz identidad (existen correlaciones)
library(psych)
# Realizar el test de Bartlett
bartlett_result <- cortest.bartlett(cor_matrix, n = 200)
cat("RESULTADOS DEL TEST:\n")
## RESULTADOS DEL TEST:
cat("Chi-cuadrado:", round(bartlett_result$chisq, 4), "\n")
## Chi-cuadrado: 1026.381
cat("Grados de libertad:", bartlett_result$df, "\n")
## Grados de libertad: 66
cat("P-valor:", format.pval(bartlett_result$p.value), "\n")
## P-valor: < 2.22e-16
cat("Nivel de significancia: α = 0.05\n\n")
## Nivel de significancia: α = 0.05
cat("DECISIÓN:\n")
## DECISIÓN:
if(bartlett_result$p.value < 0.05) {
cat("✅ P-valor < 0.05 → RECHAZAMOS H0\n")
cat("✅ CONCLUSIÓN: Existen correlaciones significativas entre las variables\n")
cat("✅ INTERPRETACIÓN: El PCA es APROPIADO para este dataset\n")
} else {
cat("❌ P-valor ≥ 0.05 → NO RECHAZAMOS H0\n")
cat("❌ CONCLUSIÓN: No hay evidencia de correlaciones significativas\n")
cat("❌ INTERPRETACIÓN: El PCA es CUESTIONABLE para este dataset\n")
}
## ✅ P-valor < 0.05 → RECHAZAMOS H0
## ✅ CONCLUSIÓN: Existen correlaciones significativas entre las variables
## ✅ INTERPRETACIÓN: El PCA es APROPIADO para este dataset
pca <- prcomp(data_scaled, center=TRUE, scale.=TRUE)
summary(pca) # Ver varianza explicada
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 1.9424 1.4299 1.07791 1.02607 0.96207 0.92509 0.83331
## Proportion of Variance 0.3144 0.1704 0.09682 0.08773 0.07713 0.07132 0.05787
## Cumulative Proportion 0.3144 0.4848 0.58160 0.66933 0.74646 0.81778 0.87565
## PC8 PC9 PC10 PC11 PC12
## Standard deviation 0.77727 0.60756 0.49741 0.40414 0.32896
## Proportion of Variance 0.05035 0.03076 0.02062 0.01361 0.00902
## Cumulative Proportion 0.92599 0.95675 0.97737 0.99098 1.00000
Scree Plot:
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_eig(pca, addlabels=TRUE) # Punto de inflexión en 3 componentes
Autovalores > 1:
pca$sdev^2 # Retener componentes con valor >1
## [1] 3.7727421 2.0445238 1.1618980 1.0528114 0.9255855 0.8557946 0.6944059
## [8] 0.6041447 0.3691261 0.2474192 0.1633308 0.1082177
Componente | Eigenvalue | Retener |
---|---|---|
PC1 | 3.77 | ✅ Sí |
PC2 | 2.04 | ✅ Sí |
PC3 | 1.17 | ✅ Sí |
PC4 | 1.05 | ✅ Sí |
PC5 | 0.92 | ❌ No |
N° Componentes | Varianza Acumulada | Evaluación |
---|---|---|
2 | 48.48% | Insuficiente |
3 | 58.16% | Aceptable mínimo |
4 | 66.93% | Bueno |
5 | 74.65% | Muy bueno |
6 | 81.78% | Excelente |
# Usar primeros 3 componentes
pca_scores_3 <- pca$x[, 1:3]
var_explicada_3 <- 58.16
# Usar primeros 4-5 componentes
pca_scores_4 <- pca$x[, 1:4] # 66.93% varianza
pca_scores_5 <- pca$x[, 1:5] # 74.65% varianza
# Usar primeros 6 componentes pca_scores_6 <- pca$x[, 1:6] var_explicada_6 <- 81.78
loadings <- pca$rotation[,1:4]
print(loadings) # Identificar variables con mayor peso
## PC1 PC2 PC3 PC4
## Frecuencia_Compra 0.41538950 0.13001278 0.270415559 0.146475848
## Gasto_Promedio 0.38537915 0.18553261 0.339342657 0.151809236
## Visita_Online 0.38292901 -0.31907705 0.006170127 0.107330423
## Click_Ads 0.26962098 -0.46385525 0.011693893 -0.111644757
## Tiempo_Redes 0.28675196 -0.33700513 -0.187512150 0.184708798
## Satisfaccion 0.38306308 0.30007066 -0.169368056 -0.105917924
## Lealtad 0.25604628 0.31652454 -0.185616957 -0.167477412
## Edad -0.06886965 0.03253912 0.543993727 -0.087297495
## Punt_Alimentos -0.06437650 0.07319671 0.258029755 0.786183723
## Punt_Electro 0.05071585 -0.11809293 0.573794097 -0.473895884
## Recibe_Ofertas 0.14605498 -0.47418379 -0.054721236 0.006261514
## Recomendacion 0.36371576 0.28755360 -0.136031468 -0.088360435
# Variables con mayor peso en PC1 (|loading| > 0.3)
pc1_importantes <- loadings[abs(loadings[,1]) > 0.3, 1]
pc1_importantes[order(abs(pc1_importantes), decreasing = TRUE)]
## Frecuencia_Compra Gasto_Promedio Satisfaccion Visita_Online
## 0.4153895 0.3853791 0.3830631 0.3829290
## Recomendacion
## 0.3637158
Interpretación:
- Frecuencia_Compra (0.415): Mayor frecuencia de compra
-Gasto_Promedio (0.385): Mayor gasto por
transacción
- Visita_Online (0.383): Mayor actividad en plataforma
digital
- Satisfacción (0.383): Mayor nivel de satisfacción
- Recomendación (0.364): Mayor probabilidad de recomendar
Este componente diferencia entre clientes muy activos y comprometidos vs. clientes poco activos.
# Variables con mayor peso en PC2 (|loading| > 0.3)
pc2_importantes <- loadings[abs(loadings[,2]) > 0.3, 2]
pc2_importantes[order(abs(pc2_importantes), decreasing = TRUE)]
## Recibe_Ofertas Click_Ads Tiempo_Redes Visita_Online Lealtad
## -0.4741838 -0.4638553 -0.3370051 -0.3190770 0.3165245
## Satisfaccion
## 0.3000707
Interpretación:
- Recibe_Ofertas (-0.474): Menor receptividad a ofertas
- Click_Ads (-0.464): Menor interacción con publicidad
- Tiempo_Redes (-0.337): Menos tiempo en redes sociales
- Visita_Online (-0.319): Menor actividad online
- Lealtad (0.317): Mayor lealtad tradicional
Este componente contrasta clientes resistentes al marketing digital vs. clientes receptivos.
# Variables con mayor peso en PC3 (|loading| > 0.25)
pc3_importantes <- loadings[abs(loadings[,3]) > 0.25, 3]
pc3_importantes[order(abs(pc3_importantes), decreasing = TRUE)]
## Punt_Electro Edad Gasto_Promedio Frecuencia_Compra
## 0.5737941 0.5439937 0.3393427 0.2704156
## Punt_Alimentos
## 0.2580298
Interpretación:
- Punt_Electro (0.574): Preferencia por productos electrónicos
- Edad (0.544): Mayor edad
- Gasto_Promedio (0.339): Mayor gasto promedio
- Punt_Alimentos (0.258): Cierta preferencia por alimentos
Asocia clientes de mayor edad con preferencia por electrónicos y mayor poder adquisitivo.
# Variables con mayor peso en PC4 (|loading| > 0.4)
pc4_importantes <- loadings[abs(loadings[,4]) > 0.4, 4]
pc4_importantes[order(abs(pc4_importantes), decreasing = TRUE)]
## Punt_Alimentos Punt_Electro
## 0.7861837 -0.4738959
Interpretación:
- Punt_Alimentos (0.786): Fuerte preferencia por alimentos
- Punt_Electro (-0.474): Menor interés en electrónicos Separa claramente clientes especializados en alimentos vs. electrónicos.
# Visualizar loadings
library(factoextra)
fviz_pca_var(pca, col.var = "contrib",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
# Cargar librerías necesarias
library(cluster)
library(factoextra)
library(ggplot2)
library(dplyr)
##
## 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(gridExtra)
##
## Adjuntando el paquete: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
componentes <- pca$x[,1:4]
# Método : Usando fviz_nbclust (combinado)
# -----------------------------------------
set.seed(123)
# Método del codo usando fviz_nbclust
p4 <- fviz_nbclust(componentes, kmeans, method = "wss", k.max = 10) +
labs(title = "Método del Codo (fviz)") +
theme_minimal()
# Método de la silueta usando fviz_nbclust
p5 <- fviz_nbclust(componentes, kmeans, method = "silhouette", k.max = 10) +
labs(title = "Método de la Silueta (fviz)") +
theme_minimal()
# Mostrar gráficos combinados
grid.arrange(p4, p5, ncol = 2)
# Aplicar k-means final
set.seed(123)
kmeans_final <- kmeans(componentes, centers = 2, nstart = 25)
# Agregar clusters al dataset original
datos_con_cluster <- cbind(componentes, cluster = (kmeans_final$cluster))
# Gráfico de clusters en las dos primeras componentes principales
p6 <- ggplot(datos_con_cluster, aes(x = PC1, y = PC2, color = cluster)) +
geom_point(size = 2, alpha = 0.7) +
stat_ellipse(type = "confidence", level = 0.95) +
labs(title = "Clusters en Componentes Principales PC1 vs PC2",
x = "PC1 (Cliente Activo y Comprometido)",
y = "PC2 (Receptividad Marketing Digital)",
color = "Cluster") +
theme_minimal() +
theme(legend.position = "bottom")
print(p6)
## Unrecognized ellipse type
datos_con_cluster=as.data.frame(datos_con_cluster)
# Calcular estadísticas descriptivas por cluster
cluster_stats <- datos_con_cluster %>%
group_by(cluster) %>%
summarise(
n = n(),
PC1_mean = round(mean(PC1), 3),
PC2_mean = round(mean(PC2), 3),
PC3_mean = round(mean(PC3), 3),
PC4_mean = round(mean(PC4), 3),
.groups = 'drop'
)
cat("\nCARACTERÍSTICAS DE CADA CLUSTER:\n")
##
## CARACTERÍSTICAS DE CADA CLUSTER:
cat("===============================\n")
## ===============================
print(cluster_stats)
## # A tibble: 2 × 6
## cluster n PC1_mean PC2_mean PC3_mean PC4_mean
## <dbl> <int> <dbl> <dbl> <dbl> <dbl>
## 1 1 83 -1.90 -0.226 -0.114 -0.053
## 2 2 117 1.35 0.16 0.081 0.038
PC1
Cluster 1 (-1.90): Valores muy bajos en PC1 → Clientes con bajo “Valor Integral” (ej: baja frecuencia de compra, gasto bajo, menor satisfacción/lealtad).
Cluster 2 (+1.35): Valores altos en PC1 → Clientes con alto “Valor Integral” (compra frecuente, gasto alto, alta lealtad).
Interpretación: PC1 suele agrupar variables como
Frecuencia_Compra
,
Gasto_Promedio
,
Lealtad
y
Satisfaccion
.
PC2
Diferencias menores entre clusters, pero:
Cluster 1 (-0.226): Ligero bajo engagement digital.
Cluster 2 (+0.16): Ligero alto engagement digital.
Interpretación: PC2 suele representar variables
como Visita_Online
,
Click_Ads
,
Tiempo_Redes
.
PC3 y PC4
Características:
Bajo valor integral (PC1).
Menor interacción digital (PC2).
Recomendaciones:
Campañas de reactivación (descuentos, recomendaciones personalizadas).
Mejorar experiencia de compra para aumentar satisfacción.
Características:
Alto valor integral (PC1).
Mayor engagement digital (PC2).
Recomendaciones:
Programas de fidelización (recompensas, acceso exclusivo).
Upselling basado en preferencias históricas.