Estadística Descriptiva

Column

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

Tabla de Estadísticas Descriptivas

Gráficos Univ. y Biv.

Column

Gráficos Univariados (Histogramas)

Gráficos Bivariados (vs Gasto Anual)

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

Column

Creación de AvgSessionGroup

Se ha creado la variable categórica dividiendo la longitud de sesión en 4 segmentos:

Column

Estadísticas de Gasto por Grupo

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

Column

Distribución del Gasto por Grupo de Sesión

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

Column

Matriz de Correlaciones

Column

Magnitud de correlaciones con Variable Respuesta

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

Column

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

Cálculo de Estimadores (Beta) y Resultados

Interpretación Final de Coeficientes

El modelo tiene un \(R^2\) de 98%, lo que indica un ajuste excelente.

  • Intercepto (-1051.59): Valor teórico negativo, indica que sin actividad, el modelo base no aplica (ajuste matemático).
  • Avg. Session Length (25.73): Por cada minuto extra de sesión promedio, el gasto anual aumenta en $25.73, manteniendo lo demás constante.
  • Time on App (38.71): Por cada minuto extra en la App, el gasto sube $38.71. Es más efectivo que la sesión general.
  • Time on Website (0.44): Por cada minuto extra en la Web, el gasto sube solo $0.44. Esto confirma la baja correlación vista antes.
  • Length of Membership (61.58): 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.

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