Análisis de las medidas de tendencia y dispersión:
Análisis Visual:
Se ha creado la variable categórica dividiendo la longitud de sesión en 4 segmentos:
Se observa una tendencia creciente en el gasto medio a medida que aumenta la duración de la sesión. * El grupo con sesiones más largas [34, 36.2) gasta en promedio considerablemente más ($539.81) que el grupo con sesiones más cortas ($460.92). * Esto sugiere que retener al usuario más tiempo en la sesión (engagement) puede traducirse en mayor facturación.
Se desea estimar el modelo: \[ YearlyAmountSpent_i = \beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} + \beta_3 x_{3i} + \beta_4 x_{4i} + \epsilon_i \]
Utilizando Álgebra Matricial: \[ \hat{\beta} = (X'X)^{-1}X'Y \]
Donde: * \(x_1\): Avg.Session.Length * \(x_2\): Time.on.App * \(x_3\): Time.on.Website * \(x_4\): Length.of.Membership
El modelo tiene un \(R^2\) de 98%, lo que indica un ajuste excelente.
Conclusión: La estrategia debe enfocarse en fidelización (Membresía) y en mejorar la experiencia en la App Móvil.
---
title: "Aplicación de todas las etapas del proceso KDD en un contexto analítico"
subtitle: "Tarea 4 - Minería de Datos con R"
author: "Rafael Afonso Porto"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
theme: yeti
social: menu
source_code: embed
---
```{r setup, include=FALSE}
# ==========================================================================
# CONFIGURACIÓN INICIAL Y CARGA DE LIBRERÍAS
# ==========================================================================
library(flexdashboard)
library(readr)
library(dplyr)
library(ggplot2)
library(tidyr)
library(kableExtra)
library(corrplot)
library(plotly)
library(DT)
library(scales)
# Funciones auxiliares para estadística descriptiva
asimetria <- function(x) {
n <- length(x)
media <- mean(x, na.rm = TRUE)
desv <- sd(x, na.rm = TRUE)
sum((x - media)^3) / (n * desv^3)
}
curtosis <- function(x) {
n <- length(x)
media <- mean(x, na.rm = TRUE)
desv <- sd(x, na.rm = TRUE)
sum((x - media)^4) / (n * desv^4) - 3
}
# ==========================================================================
# CARGA Y LIMPIEZA DE DATOS
# ==========================================================================
# Asegúrate de tener el archivo en la ruta correcta
analisis_ecommerce <- read.csv("datos/ecommerce.txt", sep = ",")
# Renombrar columnas (Quitando espacios y caracteres conflictivos)
names(analisis_ecommerce) <- c("Email", "Address", "Avatar",
"Avg.Session.Length",
"Time.on.App",
"Time.on.Website",
"Length.of.Membership",
"Yearly.Amount.Spent")
# Separar variables cuantitativas para análisis
variables_excluir <- c("Email", "Address", "Avatar")
variables_cuantitativas <- analisis_ecommerce %>%
select(-all_of(variables_excluir))
```
# Estadística Descriptiva {data-icon="fa-table"}
## Column {data-width="400"}
### Interpretación de los Resultados
**Análisis de las medidas de tendencia y dispersión:**
- **Yearly Amount Spent:** La variable objetivo tiene un promedio de gasto anual de aproximadamente **\$499.31**. La mediana es muy cercana a la media, lo que sugiere una distribución simétrica.
- **Avg. Session Length:** Las sesiones duran en promedio 33 minutos con una desviación estándar baja (aprox. 1 minuto), indicando consistencia en el comportamiento de navegación.
- **Time on App vs Website:** Los usuarios pasan ligeramente más tiempo en la Web (37 min) que en la App (12 min), sin embargo, veremos más adelante cuál impacta más en el gasto.
- **Forma (Asimetría y Curtosis):** La mayoría de las variables presentan coeficientes de asimetría cercanos a 0 y curtosis cercanas a 0 (o ligeramente negativas), lo que indica distribuciones muy similares a la normal (mesocúrticas/platicúrticas) y sin sesgos fuertes.
## Column {data-width="600"}
### Tabla de Estadísticas Descriptivas
```{r}
# Cálculo de estadísticas
estadisticas_descriptivas <- data.frame(
Variable = character(), Media = numeric(), Mediana = numeric(),
Desviacion = numeric(), Minimo = numeric(), Maximo = numeric(),
Asimetria = numeric(), Curtosis = numeric(), stringsAsFactors = FALSE
)
for (col in names(variables_cuantitativas)) {
datos <- variables_cuantitativas[[col]]
estadisticas_descriptivas <- rbind(estadisticas_descriptivas, data.frame(
Variable = col,
Media = round(mean(datos, na.rm = TRUE), 3),
Mediana = round(median(datos, na.rm = TRUE), 3),
Desviacion = round(sd(datos, na.rm = TRUE), 3),
Minimo = round(min(datos, na.rm = TRUE), 3),
Maximo = round(max(datos, na.rm = TRUE), 3),
Asimetria = round(asimetria(datos), 3),
Curtosis = round(curtosis(datos), 3)
))
}
# Mostrar tabla interactiva
datatable(estadisticas_descriptivas, options = list(pageLength = 10, dom = 't'), rownames = FALSE) %>%
formatStyle('Variable', fontWeight = 'bold')
```
# Gráficos Univ. y Biv. {data-icon="fa-chart-bar"}
## Column {.tabset}
### Gráficos Univariados (Histogramas)
```{r}
# Transformar datos a formato largo para graficar todos juntos con facet_wrap
datos_long <- variables_cuantitativas %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")
p_uni <- ggplot(datos_long, aes(x = Valor)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#3498db", color = "white", alpha = 0.7) +
geom_density(color = "#e74c3c", size = 1) +
facet_wrap(~Variable, scales = "free") +
theme_minimal() +
labs(title = "Distribución de Variables Cuantitativas", y = "Densidad")
ggplotly(p_uni)
```
### Gráficos Bivariados (vs Gasto Anual)
```{r}
# Crear gráficos de dispersión contra Yearly Amount Spent
# Usamos gridExtra para mostrar todos o facets, aquí usaremos facets manuales
datos_bivariados <- variables_cuantitativas %>%
select(-Yearly.Amount.Spent) %>%
pivot_longer(cols = everything(), names_to = "Variable_Indep", values_to = "Valor") %>%
mutate(Gasto = rep(variables_cuantitativas$Yearly.Amount.Spent, times = 4))
p_bi <- ggplot(datos_bivariados, aes(x = Valor, y = Gasto)) +
geom_point(alpha = 0.5, color = "#2c3e50") +
geom_smooth(method = "lm", color = "#e74c3c", se = FALSE) +
facet_wrap(~Variable_Indep, scales = "free_x") +
theme_bw() +
labs(title = "Correlación Visual con Yearly Amount Spent", y = "Gasto Anual")
ggplotly(p_bi)
```
### Interpretación
**Análisis Visual:**
1. **Univariado:** Se confirman visualmente las estadísticas del punto anterior. Las variables siguen una distribución de "campana" (normal), sin valores atípicos extremos que deformen la escala.
2. **Bivariado (Dispersión):**
- **Length of Membership:** Muestra la correlación positiva más clara y fuerte. A mayor antigüedad, mayor gasto (la línea roja es empinada).
- **Time on App:** Muestra una relación positiva moderada.
- **Time on Website:** La nube de puntos es muy dispersa y la línea es casi plana, indicando que no hay una relación fuerte entre el tiempo en la web y el gasto.
- **Avg Session Length:** Relación positiva leve.
# Agrupación {data-icon="fa-users"}
## Column {data-width="500"}
### Creación de AvgSessionGroup
Se ha creado la variable categórica dividiendo la longitud de sesión en 4 segmentos:
```{r}
# Crear la variable de agrupación
analisis_ecommerce <- analisis_ecommerce %>%
mutate(
AvgSessionGroup = cut(Avg.Session.Length,
breaks = c(29, 32, 33, 34, 36.2),
labels = c("[29, 32)", "[32, 33)", "[33, 34)", "[34, 36.2)"),
include.lowest = FALSE, right = FALSE)
)
# Gráfico de conteo
p_barras <- ggplot(analisis_ecommerce, aes(x = AvgSessionGroup)) +
geom_bar(fill = "#1abc9c", color = "black", alpha = 0.8) +
labs(title = "Cantidad de Clientes por Grupo de Sesión", x = "Grupo", y = "Frecuencia") +
theme_minimal()
ggplotly(p_barras)
```
## Column {data-width="500"}
### Estadísticas de Gasto por Grupo
```{r}
estadisticas_grupo <- analisis_ecommerce %>%
group_by(AvgSessionGroup) %>%
summarise(
Media_Gasto = round(mean(Yearly.Amount.Spent, na.rm = TRUE), 2),
Mediana_Gasto = round(median(Yearly.Amount.Spent, na.rm = TRUE), 2),
Desv_Std = round(sd(Yearly.Amount.Spent, na.rm = TRUE), 2),
Clientes = n()
)
datatable(estadisticas_grupo, options = list(dom = 't'))
```
### Comentarios
Se observa una **tendencia creciente** en el gasto medio a medida que aumenta la duración de la sesión. \* El grupo con sesiones más largas **[34, 36.2)** gasta en promedio considerablemente más (\$539.81) que el grupo con sesiones más cortas (\$460.92). \* Esto sugiere que retener al usuario más tiempo en la sesión (engagement) puede traducirse en mayor facturación.
# Boxplots {data-icon="fa-box-open"}
## Column
### Distribución del Gasto por Grupo de Sesión
```{r}
p_box <- ggplot(analisis_ecommerce, aes(x = AvgSessionGroup, y = Yearly.Amount.Spent, fill = AvgSessionGroup)) +
geom_boxplot(alpha = 0.7, outlier.colour = "red", outlier.shape = 1) +
stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white") +
labs(title = "Yearly Amount Spent por AvgSessionGroup",
x = "Grupo de Sesión",
y = "Gasto Anual ($)") +
scale_fill_brewer(palette = "Spectral") +
theme_minimal() +
theme(legend.position = "none")
ggplotly(p_box)
```
### Interpretación de Boxplots
- **Cajas (IQR):** Las cajas se desplazan hacia arriba conforme avanzamos de grupo, confirmando que no solo el promedio, sino toda la distribución de gasto se mueve a valores más altos.
- **Dispersión:** La altura de las cajas es relativamente similar, indicando una variabilidad de gasto parecida dentro de cada grupo.
- **Outliers:** Se observan algunos puntos rojos (valores atípicos) en los extremos, representando clientes que gastan mucho más o mucho menos de lo esperado para su grupo.
# Correlaciones {data-icon="fa-project-diagram"}
## Column {data-width="500"}
### Matriz de Correlaciones
```{r}
matriz_cor <- cor(variables_cuantitativas, use = "complete.obs")
# Usamos corrplot renderizado como imagen estática pues es más limpio para matrices
corrplot(matriz_cor, method = "color", type = "upper",
tl.col = "black", tl.srt = 45, addCoef.col = "black", number.cex = 0.7,
col = colorRampPalette(c("#e74c3c", "white", "#3498db"))(200))
```
## Column {data-width="500"}
### Magnitud de correlaciones con Variable Respuesta
```{r}
cor_target <- data.frame(
Variable = rownames(matriz_cor),
Correlacion = round(matriz_cor[, "Yearly.Amount.Spent"], 4)
) %>%
filter(Variable != "Yearly.Amount.Spent") %>%
arrange(desc(abs(Correlacion)))
datatable(cor_target, options = list(dom = 't'), rownames = FALSE)
```
### Interpretación
1. **Length of Membership (0.809):** Correlación **muy fuerte y positiva**. Es el predictor más importante. Fidelizar clientes es la clave del negocio.
2. **Time on App (0.499):** Correlación moderada positiva. La App es más efectiva para generar ventas que la web.
3. **Avg. Session Length (0.355):** Correlación débil-moderada positiva.
4. **Time on Website (-0.003):** Correlación prácticamente nula. Invertir en optimizar el sitio web podría no tener retorno inmediato en el gasto anual actual.
# Regresión MCO {data-icon="fa-calculator"}
## Column {data-width="400"}
### Modelo de Regresión Lineal Múltiple
Se desea estimar el modelo: $$ YearlyAmountSpent_i = \beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} + \beta_3 x_{3i} + \beta_4 x_{4i} + \epsilon_i $$
Utilizando Álgebra Matricial: $$ \hat{\beta} = (X'X)^{-1}X'Y $$
Donde: \* $x_1$: Avg.Session.Length \* $x_2$: Time.on.App \* $x_3$: Time.on.Website \* $x_4$: Length.of.Membership
## Column {data-width="600"}
### Cálculo de Estimadores (Beta) y Resultados
```{r}
# 1. Definir matrices X e Y
X <- as.matrix(cbind(
intercept = 1,
x1 = analisis_ecommerce$Avg.Session.Length,
x2 = analisis_ecommerce$Time.on.App,
x3 = analisis_ecommerce$Time.on.Website,
x4 = analisis_ecommerce$Length.of.Membership
))
Y <- as.matrix(analisis_ecommerce$Yearly.Amount.Spent)
# 2. Calcular Betas (Mínimos Cuadrados Ordinarios)
# Beta = inv(t(X) * X) * t(X) * Y
beta_hat <- solve(t(X) %*% X) %*% t(X) %*% Y
# Presentar resultados en una tabla bonita
resultados_beta <- data.frame(
Parametro = c("Intercepto (β0)", "Avg.Session (β1)", "Time.App (β2)", "Time.Web (β3)", "Membership (β4)"),
Estimacion = as.vector(beta_hat)
)
datatable(resultados_beta, options = list(dom = 't'), rownames = FALSE) %>%
formatRound('Estimacion', 4)
# Cálculo del R2 para validar
Y_hat <- X %*% beta_hat
SSR <- sum((Y_hat - mean(Y))^2)
SST <- sum((Y - mean(Y))^2)
R2 <- SSR / SST
```
### Interpretación Final de Coeficientes
El modelo tiene un $R^2$ de **`r percent(R2)`**, lo que indica un ajuste excelente.
- **Intercepto (`r round(beta_hat[1], 2)`):** Valor teórico negativo, indica que sin actividad, el modelo base no aplica (ajuste matemático).
- **Avg. Session Length (`r round(beta_hat[2], 2)`):** Por cada minuto extra de sesión promedio, el gasto anual aumenta en \$25.73, manteniendo lo demás constante.
- **Time on App (`r round(beta_hat[3], 2)`):** Por cada minuto extra en la App, el gasto sube **\$38.71**. Es más efectivo que la sesión general.
- **Time on Website (`r round(beta_hat[4], 2)`):** Por cada minuto extra en la Web, el gasto sube solo \$0.44. Esto confirma la baja correlación vista antes.
- **Length of Membership (`r round(beta_hat[5], 2)`):** Por cada año de membresía, el gasto aumenta **\$61.58**. Es el factor más impactante.
**Conclusión:** La estrategia debe enfocarse en **fidelización (Membresía)** y en mejorar la experiencia en la **App Móvil**.