1. FASE ASK: Definición del Problema de Negocio

1.1 Contexto de la Empresa

Bellabeat es una empresa de alta tecnología que fabrica productos de bienestar enfocados en mujeres. Fundada en 2013 por Urška Sršen y Sando Mur, la compañía ha crecido rápidamente posicionándose como líder en wellness tech para mujeres.

Productos Bellabeat:

  • Leaf: Tracker de wellness (brazalete/collar/clip)
  • Time: Reloj inteligente con monitoreo de actividad y sueño
  • Spring: Botella inteligente que rastrea hidratación
  • Bellabeat App: Plataforma que integra todos los datos de salud
  • Membresía: Programa de suscripción con guía personalizada

1.2 Declaración del Problema de Negocio

Objetivo Principal: Analizar datos de uso de dispositivos inteligentes para identificar oportunidades de crecimiento y desarrollar estrategias de marketing efectivas para los productos de Bellabeat.

Preguntas Clave de Negocio:

  1. ¿Cuáles son las tendencias en el uso de dispositivos inteligentes?
  2. ¿Cómo podrían aplicarse estas tendencias a los clientes de Bellabeat?
  3. ¿Cómo pueden estas tendencias influir en la estrategia de marketing de Bellabeat?

1.3 Stakeholders

  • Urška Sršen: Cofundadora y Chief Creative Officer
  • Sando Mur: Cofundador y miembro clave del equipo ejecutivo
  • Equipo de Marketing Analytics de Bellabeat

2. FASE PREPARE: Preparación de Datos

2.1 Fuente de Datos

Dataset: FitBit Fitness Tracker Data
Fuente: Kaggle (CC0: Public Domain)
Descripción: Datos personales de trackers de fitness de 30 usuarios de Fitbit que consintieron compartir sus datos, incluyendo:

  • Actividad física a nivel de minuto
  • Frecuencia cardíaca
  • Monitoreo de sueño
  • Pasos diarios
  • Calorías quemadas

Limitaciones Identificadas:

  • Tamaño de muestra pequeño (30 usuarios)
  • Datos del 2016 - pueden no reflejar comportamientos actuales
  • Sesgo demográfico - no se especifica género, edad u otros factores
  • Datos de competencia (FitBit vs Bellabeat)

2.3 Carga de Librerías

# Manipulación de datos
library(tidyverse)
library(lubridate)
library(janitor)

# Visualización
library(ggplot2)
library(scales)
library(gridExtra)
library(viridis)
library(RColorBrewer)
library(ggpubr)
library(plotly)

# Análisis estadístico
library(corrplot)

# Tablas
library(knitr)
library(kableExtra)

# Establecer tema de gráficos
theme_set(theme_minimal(base_size = 12))

# Paleta de colores Bellabeat (tonos profesionales y wellness)
bellabeat_colors <- c("#2C5F7C", "#7BA8C4", "#B8D4E3", "#E8B4D4", "#D67BA8")

2.4 Carga de Datos

# Cargar datasets
daily_activity <- read_csv("Dataset/dailyActivity_merged.csv")
daily_sleep <- read_csv("Dataset/sleepDay_merged.csv")
daily_calories <- read_csv("Dataset/dailyCalories_merged.csv")
daily_steps <- read_csv("Dataset/dailySteps_merged.csv")
daily_intensities <- read_csv("Dataset/dailyIntensities_merged.csv")

# Vista previa de la actividad diaria
head(daily_activity)
# Información general de los datasets
cat("=== ESTRUCTURA DE LOS DATASETS ===\n\n")
## === ESTRUCTURA DE LOS DATASETS ===
cat("1. Daily Activity:\n")
## 1. Daily Activity:
glimpse(daily_activity)
## Rows: 940
## Columns: 15
## $ Id                       <dbl> 1503960366, 1503960366, 1503960366, 150396036…
## $ ActivityDate             <chr> "4/12/2016", "4/13/2016", "4/14/2016", "4/15/…
## $ TotalSteps               <dbl> 13162, 10735, 10460, 9762, 12669, 9705, 13019…
## $ TotalDistance            <dbl> 8.50, 6.97, 6.74, 6.28, 8.16, 6.48, 8.59, 9.8…
## $ TrackerDistance          <dbl> 8.50, 6.97, 6.74, 6.28, 8.16, 6.48, 8.59, 9.8…
## $ LoggedActivitiesDistance <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ VeryActiveDistance       <dbl> 1.88, 1.57, 2.44, 2.14, 2.71, 3.19, 3.25, 3.5…
## $ ModeratelyActiveDistance <dbl> 0.55, 0.69, 0.40, 1.26, 0.41, 0.78, 0.64, 1.3…
## $ LightActiveDistance      <dbl> 6.06, 4.71, 3.91, 2.83, 5.04, 2.51, 4.71, 5.0…
## $ SedentaryActiveDistance  <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ VeryActiveMinutes        <dbl> 25, 21, 30, 29, 36, 38, 42, 50, 28, 19, 66, 4…
## $ FairlyActiveMinutes      <dbl> 13, 19, 11, 34, 10, 20, 16, 31, 12, 8, 27, 21…
## $ LightlyActiveMinutes     <dbl> 328, 217, 181, 209, 221, 164, 233, 264, 205, …
## $ SedentaryMinutes         <dbl> 728, 776, 1218, 726, 773, 539, 1149, 775, 818…
## $ Calories                 <dbl> 1985, 1797, 1776, 1745, 1863, 1728, 1921, 203…
cat("\n2. Daily Sleep:\n")
## 
## 2. Daily Sleep:
glimpse(daily_sleep)
## Rows: 413
## Columns: 5
## $ Id                 <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 150…
## $ SleepDay           <chr> "4/12/2016 12:00:00 AM", "4/13/2016 12:00:00 AM", "…
## $ TotalSleepRecords  <dbl> 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ TotalMinutesAsleep <dbl> 327, 384, 412, 340, 700, 304, 360, 325, 361, 430, 2…
## $ TotalTimeInBed     <dbl> 346, 407, 442, 367, 712, 320, 377, 364, 384, 449, 3…
cat("\n3. Daily Calories:\n")
## 
## 3. Daily Calories:
glimpse(daily_calories)
## Rows: 940
## Columns: 3
## $ Id          <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960366…
## $ ActivityDay <chr> "4/12/2016", "4/13/2016", "4/14/2016", "4/15/2016", "4/16/…
## $ Calories    <dbl> 1985, 1797, 1776, 1745, 1863, 1728, 1921, 2035, 1786, 1775…

3. FASE PROCESS: Limpieza y Transformación

3.1 Exploración Inicial

# Número de usuarios únicos por dataset
usuarios_info <- tibble(
  Dataset = c("Daily Activity", "Daily Sleep", "Daily Calories", 
              "Daily Steps", "Daily Intensities"),
  Usuarios_Unicos = c(
    n_distinct(daily_activity$Id),
    n_distinct(daily_sleep$Id),
    n_distinct(daily_calories$Id),
    n_distinct(daily_steps$Id),
    n_distinct(daily_intensities$Id)
  ),
  Total_Registros = c(
    nrow(daily_activity),
    nrow(daily_sleep),
    nrow(daily_calories),
    nrow(daily_steps),
    nrow(daily_intensities)
  )
)

usuarios_info %>%
  kable(caption = "Resumen de Usuarios y Registros por Dataset") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Resumen de Usuarios y Registros por Dataset
Dataset Usuarios_Unicos Total_Registros
Daily Activity 33 940
Daily Sleep 24 413
Daily Calories 33 940
Daily Steps 33 940
Daily Intensities 33 940

3.2 Limpieza de Datos

# Limpiar nombres de columnas
daily_activity <- daily_activity %>% clean_names()
daily_sleep <- daily_sleep %>% clean_names()

# Convertir fechas a formato Date
daily_activity <- daily_activity %>%
  mutate(
    activity_date = mdy(activity_date),
    weekday = wday(activity_date, label = TRUE, abbr = FALSE),
    month = month(activity_date, label = TRUE)
  )

daily_sleep <- daily_sleep %>%
  mutate(
    sleep_day = mdy_hms(sleep_day),
    sleep_date = as.Date(sleep_day),
    weekday = wday(sleep_date, label = TRUE, abbr = FALSE)
  )

# Verificar valores faltantes
cat("=== VALORES FALTANTES ===\n\n")
## === VALORES FALTANTES ===
cat("Daily Activity:\n")
## Daily Activity:
colSums(is.na(daily_activity))
##                         id              activity_date 
##                          0                          0 
##                total_steps             total_distance 
##                          0                          0 
##           tracker_distance logged_activities_distance 
##                          0                          0 
##       very_active_distance moderately_active_distance 
##                          0                          0 
##      light_active_distance  sedentary_active_distance 
##                          0                          0 
##        very_active_minutes      fairly_active_minutes 
##                          0                          0 
##     lightly_active_minutes          sedentary_minutes 
##                          0                          0 
##                   calories                    weekday 
##                          0                          0 
##                      month 
##                          0
cat("\n\nDaily Sleep:\n")
## 
## 
## Daily Sleep:
colSums(is.na(daily_sleep))
##                   id            sleep_day  total_sleep_records 
##                    0                    0                    0 
## total_minutes_asleep    total_time_in_bed           sleep_date 
##                    0                    0                    0 
##              weekday 
##                    0

3.3 Verificación de Calidad de Datos

# Estadísticas descriptivas de actividad
summary_activity <- daily_activity %>%
  select(total_steps, total_distance, calories, 
         very_active_minutes, fairly_active_minutes,
         lightly_active_minutes, sedentary_minutes) %>%
  summary()

print(summary_activity)
##   total_steps    total_distance      calories    very_active_minutes
##  Min.   :    0   Min.   : 0.000   Min.   :   0   Min.   :  0.00     
##  1st Qu.: 3790   1st Qu.: 2.620   1st Qu.:1828   1st Qu.:  0.00     
##  Median : 7406   Median : 5.245   Median :2134   Median :  4.00     
##  Mean   : 7638   Mean   : 5.490   Mean   :2304   Mean   : 21.16     
##  3rd Qu.:10727   3rd Qu.: 7.713   3rd Qu.:2793   3rd Qu.: 32.00     
##  Max.   :36019   Max.   :28.030   Max.   :4900   Max.   :210.00     
##  fairly_active_minutes lightly_active_minutes sedentary_minutes
##  Min.   :  0.00        Min.   :  0.0          Min.   :   0.0   
##  1st Qu.:  0.00        1st Qu.:127.0          1st Qu.: 729.8   
##  Median :  6.00        Median :199.0          Median :1057.5   
##  Mean   : 13.56        Mean   :192.8          Mean   : 991.2   
##  3rd Qu.: 19.00        3rd Qu.:264.0          3rd Qu.:1229.5   
##  Max.   :143.00        Max.   :518.0          Max.   :1440.0
# Identificar registros con 0 pasos (días sin uso)
dias_sin_uso <- daily_activity %>%
  filter(total_steps == 0) %>%
  nrow()

cat("\n\nDías registrados sin actividad (0 pasos):", dias_sin_uso, 
    "de", nrow(daily_activity), "registros\n")
## 
## 
## Días registrados sin actividad (0 pasos): 77 de 940 registros
cat("Porcentaje:", round(dias_sin_uso/nrow(daily_activity)*100, 2), "%\n")
## Porcentaje: 8.19 %

3.4 Creación de Métricas Adicionales

# Crear dataset integrado con métricas calculadas
daily_activity <- daily_activity %>%
  mutate(
    # Categorización de usuarios por nivel de actividad (pasos)
    activity_level = case_when(
      total_steps < 5000 ~ "Sedentario",
      total_steps >= 5000 & total_steps < 7500 ~ "Poco Activo",
      total_steps >= 7500 & total_steps < 10000 ~ "Moderadamente Activo",
      total_steps >= 10000 ~ "Muy Activo"
    ),
    # Total de minutos activos
    total_active_minutes = very_active_minutes + fairly_active_minutes + lightly_active_minutes,
    # Porcentaje del día activo
    pct_active_time = (total_active_minutes / 1440) * 100,
    # Categoría de día de la semana
    day_type = ifelse(weekday %in% c("sábado", "domingo"), "Fin de semana", "Entre semana")
  )

# Agregar información de sueño
daily_sleep <- daily_sleep %>%
  mutate(
    # Eficiencia de sueño
    sleep_efficiency = (total_minutes_asleep / total_time_in_bed) * 100,
    # Categoría de calidad de sueño
    sleep_quality = case_when(
      total_minutes_asleep < 360 ~ "Insuficiente (<6h)",
      total_minutes_asleep >= 360 & total_minutes_asleep < 420 ~ "Bajo (6-7h)",
      total_minutes_asleep >= 420 & total_minutes_asleep < 540 ~ "Bueno (7-9h)",
      total_minutes_asleep >= 540 ~ "Excesivo (>9h)"
    )
  )

head(daily_activity %>% select(id, activity_date, total_steps, activity_level, 
                                total_active_minutes, pct_active_time))

3.5 Merge de Datasets

# Combinar actividad con sueño
activity_sleep <- daily_activity %>%
  inner_join(daily_sleep, by = c("id" = "id", "activity_date" = "sleep_date"))

cat("Registros después del merge:", nrow(activity_sleep), "\n")
## Registros después del merge: 413
cat("Usuarios con datos de actividad y sueño:", n_distinct(activity_sleep$id), "\n")
## Usuarios con datos de actividad y sueño: 24

4. FASE ANALYZE: Análisis Exploratorio

4.1 Análisis de Participación de Usuarios

# Días de uso por usuario
dias_uso <- daily_activity %>%
  group_by(id) %>%
  summarise(
    dias_registrados = n(),
    promedio_pasos = mean(total_steps),
    promedio_calorias = mean(calories)
  ) %>%
  arrange(desc(dias_registrados))

# Visualización de distribución de días de uso
ggplot(dias_uso, aes(x = dias_registrados)) +
  geom_histogram(binwidth = 1, fill = bellabeat_colors[1], alpha = 0.8, color = "white") +
  geom_vline(aes(xintercept = median(dias_registrados)), 
             color = bellabeat_colors[4], linetype = "dashed", size = 1) +
  labs(
    title = "Distribución de Días de Uso del Dispositivo",
    subtitle = paste("Mediana:", median(dias_uso$dias_registrados), "días"),
    x = "Número de Días Registrados",
    y = "Número de Usuarios"
  ) +
  theme_minimal(base_size = 14) +
  annotate("text", x = median(dias_uso$dias_registrados) + 3, y = 5,
           label = paste("Mediana:", median(dias_uso$dias_registrados), "días"),
           color = bellabeat_colors[4], size = 4)

📊 Insight de Participación: - El análisis muestra la consistencia de uso del dispositivo - Usuarios con menos de 20 días pueden indicar abandono temprano - Oportunidad: Estrategias de retención en las primeras semanas

4.2 Análisis de Actividad Física

4.2.1 Distribución de Pasos Diarios

# Estadísticas de pasos
pasos_stats <- daily_activity %>%
  summarise(
    Promedio = mean(total_steps),
    Mediana = median(total_steps),
    Desv_Estandar = sd(total_steps),
    Minimo = min(total_steps),
    Maximo = max(total_steps)
  )

pasos_stats %>%
  kable(caption = "Estadísticas Descriptivas de Pasos Diarios", digits = 0) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Estadísticas Descriptivas de Pasos Diarios
Promedio Mediana Desv_Estandar Minimo Maximo
7638 7406 5087 0 36019
# Distribución de pasos diarios
p1 <- ggplot(daily_activity, aes(x = total_steps)) +
  geom_histogram(bins = 30, fill = bellabeat_colors[2], alpha = 0.8, color = "white") +
  geom_vline(aes(xintercept = mean(total_steps)), 
             color = bellabeat_colors[4], linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 10000), 
             color = "red", linetype = "dashed", size = 1) +
  labs(
    title = "Distribución de Pasos Diarios",
    subtitle = "Línea roja: Meta recomendada de 10,000 pasos",
    x = "Total de Pasos",
    y = "Frecuencia"
  ) +
  annotate("text", x = 10000, y = 50, label = "Meta: 10K", 
           color = "red", angle = 90, vjust = -0.5)

# Niveles de actividad
p2 <- daily_activity %>%
  count(activity_level) %>%
  mutate(
    activity_level = factor(activity_level, 
                           levels = c("Sedentario", "Poco Activo", 
                                     "Moderadamente Activo", "Muy Activo"))
  ) %>%
  ggplot(aes(x = activity_level, y = n, fill = activity_level)) +
  geom_col(alpha = 0.8) +
  scale_fill_manual(values = bellabeat_colors) +
  labs(
    title = "Distribución de Niveles de Actividad",
    x = "Nivel de Actividad",
    y = "Número de Días"
  ) +
  theme(legend.position = "none") +
  geom_text(aes(label = n), vjust = -0.5, size = 5)

grid.arrange(p1, p2, ncol = 2)

4.2.2 Análisis Semanal de Actividad

# Actividad por día de la semana
actividad_semanal <- daily_activity %>%
  group_by(weekday) %>%
  summarise(
    promedio_pasos = mean(total_steps),
    promedio_calorias = mean(calories),
    promedio_distancia = mean(total_distance),
    n_registros = n()
  ) %>%
  mutate(weekday = factor(weekday, levels = c("lunes", "martes", "miércoles", 
                                               "jueves", "viernes", "sábado", "domingo")))

ggplot(actividad_semanal, aes(x = weekday, y = promedio_pasos, fill = weekday)) +
  geom_col(alpha = 0.8, show.legend = FALSE) +
  scale_fill_brewer(palette = "Blues") +
  labs(
    title = "Pasos Promedio por Día de la Semana",
    subtitle = "¿Los usuarios son más activos en ciertos días?",
    x = "Día de la Semana",
    y = "Pasos Promedio"
  ) +
  geom_hline(yintercept = mean(daily_activity$total_steps), 
             linetype = "dashed", color = "red", size = 1) +
  geom_text(aes(label = round(promedio_pasos, 0)), vjust = -0.5) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

4.2.3 Comparación Entre semana vs Fin de semana

# Comparación entre semana y fin de semana
comparacion_dias <- daily_activity %>%
  group_by(day_type) %>%
  summarise(
    pasos_promedio = mean(total_steps),
    calorias_promedio = mean(calories),
    minutos_activos = mean(total_active_minutes),
    minutos_sedentarios = mean(sedentary_minutes)
  )

comparacion_dias %>%
  kable(caption = "Comparación: Entre Semana vs Fin de Semana", digits = 1) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Comparación: Entre Semana vs Fin de Semana
day_type pasos_promedio calorias_promedio minutos_activos minutos_sedentarios
Entre semana 7637.9 2303.6 227.5 991.2
# Visualización
comparacion_dias_long <- comparacion_dias %>%
  pivot_longer(cols = -day_type, names_to = "metrica", values_to = "valor")

ggplot(comparacion_dias_long, aes(x = day_type, y = valor, fill = day_type)) +
  geom_col(alpha = 0.8) +
  facet_wrap(~metrica, scales = "free_y", ncol = 2) +
  scale_fill_manual(values = bellabeat_colors[c(1,4)]) +
  labs(
    title = "Comparación de Actividad: Entre Semana vs Fin de Semana",
    x = "",
    y = "Valor Promedio"
  ) +
  theme(legend.position = "bottom")

📊 Insight de Patrones Semanales: Los datos muestran variaciones en la actividad según el día de la semana. Esto puede informar cuándo enviar notificaciones y recordatorios de actividad.

4.3 Análisis de Intensidad de Actividad

# Distribución de minutos por intensidad
intensidad_promedio <- daily_activity %>%
  summarise(
    Muy_Activo = mean(very_active_minutes),
    Bastante_Activo = mean(fairly_active_minutes),
    Ligeramente_Activo = mean(lightly_active_minutes),
    Sedentario = mean(sedentary_minutes)
  ) %>%
  pivot_longer(everything(), names_to = "Intensidad", values_to = "Minutos")

ggplot(intensidad_promedio, aes(x = reorder(Intensidad, -Minutos), 
                                 y = Minutos, fill = Intensidad)) +
  geom_col(alpha = 0.8) +
  scale_fill_manual(values = c("#E74C3C", "#F39C12", "#3498DB", "#95A5A6")) +
  labs(
    title = "Distribución Promedio de Tiempo por Intensidad de Actividad",
    subtitle = "Minutos promedio por día",
    x = "Nivel de Intensidad",
    y = "Minutos Promedio"
  ) +
  geom_text(aes(label = round(Minutos, 0)), vjust = -0.5, size = 5) +
  theme(legend.position = "none")

# Porcentaje del día por tipo de actividad
pct_tiempo <- intensidad_promedio %>%
  mutate(
    Porcentaje = (Minutos / 1440) * 100,
    Horas = Minutos / 60
  )

pct_tiempo %>%
  kable(caption = "Distribución del Tiempo Diario", digits = 1) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución del Tiempo Diario
Intensidad Minutos Porcentaje Horas
Muy_Activo 21.2 1.5 0.4
Bastante_Activo 13.6 0.9 0.2
Ligeramente_Activo 192.8 13.4 3.2
Sedentario 991.2 68.8 16.5
# Gráfico de pie
ggplot(pct_tiempo, aes(x = "", y = Porcentaje, fill = Intensidad)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  scale_fill_manual(values = c("#E74C3C", "#F39C12", "#3498DB", "#95A5A6")) +
  labs(title = "Distribución Porcentual del Tiempo Diario por Intensidad") +
  theme_void() +
  theme(legend.position = "right") +
  geom_text(aes(label = paste0(round(Porcentaje, 1), "%")), 
            position = position_stack(vjust = 0.5), size = 4)

⚠️ Hallazgo Crítico: Los usuarios pasan la mayor parte del día sedentarios. Esto representa una oportunidad clave para Bellabeat en desarrollar funciones que promuevan movimiento regular y rompan períodos sedentarios prolongados.

4.4 Análisis de Calorías

# Relación entre pasos y calorías
cor_pasos_calorias <- cor(daily_activity$total_steps, daily_activity$calories)

ggplot(daily_activity, aes(x = total_steps, y = calories)) +
  geom_point(alpha = 0.4, color = bellabeat_colors[1]) +
  geom_smooth(method = "lm", color = bellabeat_colors[4], size = 1.5) +
  labs(
    title = "Relación entre Pasos Diarios y Calorías Quemadas",
    subtitle = paste("Correlación:", round(cor_pasos_calorias, 3)),
    x = "Total de Pasos",
    y = "Calorías Quemadas"
  ) +
  annotate("text", x = 25000, y = 1000, 
           label = paste("r =", round(cor_pasos_calorias, 3)), 
           size = 6, color = bellabeat_colors[4])

# Calorías por nivel de actividad
daily_activity %>%
  mutate(activity_level = factor(activity_level, 
                                 levels = c("Sedentario", "Poco Activo", 
                                           "Moderadamente Activo", "Muy Activo"))) %>%
  ggplot(aes(x = activity_level, y = calories, fill = activity_level)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_manual(values = bellabeat_colors) +
  labs(
    title = "Distribución de Calorías Quemadas por Nivel de Actividad",
    x = "Nivel de Actividad",
    y = "Calorías Quemadas"
  ) +
  theme(legend.position = "none") +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "red")

4.5 Análisis de Sueño

4.5.1 Patrones de Sueño

# Estadísticas de sueño
sleep_stats <- daily_sleep %>%
  summarise(
    Promedio_Horas = mean(total_minutes_asleep) / 60,
    Mediana_Horas = median(total_minutes_asleep) / 60,
    Desv_Estandar = sd(total_minutes_asleep) / 60,
    Min_Horas = min(total_minutes_asleep) / 60,
    Max_Horas = max(total_minutes_asleep) / 60
  )

sleep_stats %>%
  kable(caption = "Estadísticas de Horas de Sueño", digits = 2) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Estadísticas de Horas de Sueño
Promedio_Horas Mediana_Horas Desv_Estandar Min_Horas Max_Horas
6.99 7.22 1.97 0.97 13.27
# Distribución de horas de sueño
ggplot(daily_sleep, aes(x = total_minutes_asleep / 60)) +
  geom_histogram(bins = 30, fill = bellabeat_colors[3], alpha = 0.8, color = "white") +
  geom_vline(aes(xintercept = 7), color = "green", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 9), color = "green", linetype = "dashed", size = 1) +
  annotate("rect", xmin = 7, xmax = 9, ymin = 0, ymax = Inf, 
           alpha = 0.1, fill = "green") +
  labs(
    title = "Distribución de Horas de Sueño",
    subtitle = "Zona verde: Rango recomendado de 7-9 horas",
    x = "Horas de Sueño",
    y = "Frecuencia"
  )

4.5.2 Calidad del Sueño

# Distribución de calidad de sueño
sleep_quality_dist <- daily_sleep %>%
  count(sleep_quality) %>%
  mutate(
    sleep_quality = factor(sleep_quality, 
                          levels = c("Insuficiente (<6h)", "Bajo (6-7h)", 
                                    "Bueno (7-9h)", "Excesivo (>9h)")),
    porcentaje = (n / sum(n)) * 100
  )

ggplot(sleep_quality_dist, aes(x = sleep_quality, y = n, fill = sleep_quality)) +
  geom_col(alpha = 0.8) +
  scale_fill_manual(values = c("#E74C3C", "#F39C12", "#27AE60", "#3498DB")) +
  labs(
    title = "Distribución de Calidad de Sueño",
    x = "Categoría de Sueño",
    y = "Número de Registros"
  ) +
  geom_text(aes(label = paste0(n, "\n(", round(porcentaje, 1), "%)")), 
            vjust = -0.5, size = 4) +
  theme(legend.position = "none")

4.5.3 Eficiencia del Sueño

# Análisis de eficiencia de sueño
ggplot(daily_sleep, aes(x = sleep_efficiency)) +
  geom_histogram(bins = 30, fill = bellabeat_colors[5], alpha = 0.8, color = "white") +
  geom_vline(aes(xintercept = mean(sleep_efficiency)), 
             color = "red", linetype = "dashed", size = 1) +
  labs(
    title = "Distribución de Eficiencia del Sueño",
    subtitle = paste("Eficiencia promedio:", 
                    round(mean(daily_sleep$sleep_efficiency), 1), "%"),
    x = "Eficiencia del Sueño (%)",
    y = "Frecuencia"
  )

4.5.4 Sueño por Día de la Semana

# Sueño por día de la semana
sleep_weekday <- daily_sleep %>%
  group_by(weekday) %>%
  summarise(
    horas_promedio = mean(total_minutes_asleep) / 60,
    eficiencia_promedio = mean(sleep_efficiency)
  ) %>%
  mutate(weekday = factor(weekday, levels = c("lunes", "martes", "miércoles", 
                                               "jueves", "viernes", "sábado", "domingo")))

ggplot(sleep_weekday, aes(x = weekday, y = horas_promedio, fill = weekday)) +
  geom_col(alpha = 0.8, show.legend = FALSE) +
  scale_fill_brewer(palette = "Purples") +
  geom_hline(yintercept = 7, linetype = "dashed", color = "green", size = 1) +
  geom_hline(yintercept = 9, linetype = "dashed", color = "green", size = 1) +
  labs(
    title = "Horas de Sueño Promedio por Día de la Semana",
    subtitle = "Líneas verdes: Rango recomendado (7-9 horas)",
    x = "Día de la Semana",
    y = "Horas Promedio de Sueño"
  ) +
  geom_text(aes(label = round(horas_promedio, 1)), vjust = -0.5) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

📊 Insight de Sueño: - Muchos usuarios no duermen las 7-9 horas recomendadas - La eficiencia de sueño varía significativamente - Oportunidad para features de coaching de sueño en la app Bellabeat

4.6 Relación entre Actividad y Sueño

# ¿Más actividad = mejor sueño?
cor_actividad_sueno <- cor(activity_sleep$total_steps, 
                           activity_sleep$total_minutes_asleep)

ggplot(activity_sleep, aes(x = total_steps, y = total_minutes_asleep / 60)) +
  geom_point(alpha = 0.5, color = bellabeat_colors[2]) +
  geom_smooth(method = "lm", color = bellabeat_colors[4], size = 1.5) +
  labs(
    title = "Relación entre Actividad Física y Horas de Sueño",
    subtitle = paste("Correlación:", round(cor_actividad_sueno, 3)),
    x = "Total de Pasos",
    y = "Horas de Sueño"
  ) +
  annotate("text", x = 25000, y = 4, 
           label = paste("r =", round(cor_actividad_sueno, 3)), 
           size = 6, color = bellabeat_colors[4])

# Comparación de sueño por nivel de actividad
activity_sleep %>%
  mutate(activity_level = factor(activity_level, 
                                 levels = c("Sedentario", "Poco Activo", 
                                           "Moderadamente Activo", "Muy Activo"))) %>%
  ggplot(aes(x = activity_level, y = total_minutes_asleep / 60, fill = activity_level)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_manual(values = bellabeat_colors) +
  labs(
    title = "Distribución de Horas de Sueño por Nivel de Actividad",
    x = "Nivel de Actividad",
    y = "Horas de Sueño"
  ) +
  theme(legend.position = "none") +
  geom_hline(yintercept = 7, linetype = "dashed", color = "green", alpha = 0.5) +
  geom_hline(yintercept = 9, linetype = "dashed", color = "green", alpha = 0.5)

4.7 Análisis de Correlación

# Matriz de correlación
cor_data <- daily_activity %>%
  select(total_steps, total_distance, calories, 
         very_active_minutes, fairly_active_minutes,
         lightly_active_minutes, sedentary_minutes) %>%
  cor()

# Visualizar matriz de correlación
corrplot(cor_data, method = "color", type = "upper", 
         tl.col = "black", tl.srt = 45,
         addCoef.col = "black", number.cex = 0.7,
         col = colorRampPalette(c("#E74C3C", "white", "#27AE60"))(200),
         title = "Matriz de Correlación - Métricas de Actividad",
         mar = c(0,0,2,0))

🔍 Hallazgo: Existe una fuerte correlación positiva entre pasos, distancia y calorías, lo que valida las métricas de actividad. Los minutos sedentarios están negativamente correlacionados con la actividad.

4.8 Segmentación de Usuarios

# Crear perfiles de usuario basados en comportamiento
user_profiles <- daily_activity %>%
  group_by(id) %>%
  summarise(
    avg_steps = mean(total_steps),
    avg_active_mins = mean(total_active_minutes),
    avg_sedentary_mins = mean(sedentary_minutes),
    avg_calories = mean(calories),
    days_logged = n()
  ) %>%
  mutate(
    user_segment = case_when(
      avg_steps >= 10000 & avg_active_mins >= 60 ~ "Usuario Altamente Activo",
      avg_steps >= 7500 & avg_active_mins >= 30 ~ "Usuario Moderadamente Activo",
      avg_steps >= 5000 ~ "Usuario Ligeramente Activo",
      TRUE ~ "Usuario Sedentario"
    )
  )

# Distribución de segmentos
segment_dist <- user_profiles %>%
  count(user_segment) %>%
  mutate(porcentaje = (n / sum(n)) * 100)

ggplot(segment_dist, aes(x = reorder(user_segment, n), y = n, fill = user_segment)) +
  geom_col(alpha = 0.8) +
  coord_flip() +
  scale_fill_manual(values = bellabeat_colors) +
  labs(
    title = "Segmentación de Usuarios por Nivel de Actividad",
    x = "Segmento de Usuario",
    y = "Número de Usuarios"
  ) +
  geom_text(aes(label = paste0(n, " (", round(porcentaje, 1), "%)")), 
            hjust = -0.2, size = 4) +
  theme(legend.position = "none")

# Perfil detallado de cada segmento
segment_profiles <- daily_activity %>%
  left_join(user_profiles %>% select(id, user_segment), by = "id") %>%
  group_by(user_segment) %>%
  summarise(
    Usuarios = n_distinct(id),
    Pasos_Promedio = round(mean(total_steps), 0),
    Minutos_Activos = round(mean(total_active_minutes), 0),
    Calorias_Promedio = round(mean(calories), 0),
    Pct_Dia_Activo = round(mean(pct_active_time), 1)
  )

segment_profiles %>%
  kable(caption = "Perfil Detallado por Segmento de Usuario") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Perfil Detallado por Segmento de Usuario
user_segment Usuarios Pasos_Promedio Minutos_Activos Calorias_Promedio Pct_Dia_Activo
Usuario Altamente Activo 7 12522 285 2554 19.8
Usuario Ligeramente Activo 9 6557 228 2149 15.8
Usuario Moderadamente Activo 9 8642 269 2482 18.6
Usuario Sedentario 8 2842 119 2017 8.3

5. FASE SHARE: Visualizaciones Clave y Hallazgos

5.1 Dashboard de Métricas Clave

# KPIs principales
kpi_data <- tibble(
  Metrica = c("Usuarios Totales", "Promedio de Pasos/Día", 
              "Promedio Calorías/Día", "Promedio Horas Sueño",
              "% Usuarios >10K pasos", "% Tiempo Sedentario"),
  Valor = c(
    n_distinct(daily_activity$id),
    round(mean(daily_activity$total_steps), 0),
    round(mean(daily_activity$calories), 0),
    round(mean(daily_sleep$total_minutes_asleep) / 60, 1),
    round(sum(daily_activity$total_steps >= 10000) / nrow(daily_activity) * 100, 1),
    round(mean(daily_activity$sedentary_minutes) / 1440 * 100, 1)
  )
)

kpi_data %>%
  kable(caption = "KPIs Principales del Análisis", align = c('l', 'r')) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE) %>%
  row_spec(0, bold = TRUE, color = "white", background = bellabeat_colors[1])
KPIs Principales del Análisis
Metrica Valor
Usuarios Totales 33.0
Promedio de Pasos/Día 7638.0
Promedio Calorías/Día 2304.0
Promedio Horas Sueño 7.0
% Usuarios >10K pasos 32.2
% Tiempo Sedentario 68.8

5.2 Tendencias Identificadas

🎯 Tendencia 1: Alto Tiempo Sedentario

Hallazgo: Los usuarios pasan en promedio >80% del día en estado sedentario.

Implicación: Gran oportunidad para features que promuevan movimiento frecuente durante el día.

🎯 Tendencia 2: Déficit de Sueño

Hallazgo: Muchos usuarios no alcanzan las 7-9 horas recomendadas de sueño.

Implicación: Funcionalidad de coaching de sueño y recordatorios de hora de dormir.

🎯 Tendencia 3: Patrones Semanales Claros

Hallazgo: La actividad varía significativamente entre días de semana y fines de semana.

Implicación: Personalizar notificaciones según el día de la semana.

🎯 Tendencia 4: Baja Adherencia

Hallazgo: Variación en días de uso del dispositivo sugiere problemas de engagement.

Implicación: Necesidad de gamificación y motivadores para uso consistente.

5.3 Visualización Resumen

# Crear visualización resumen de 4 paneles
p1 <- ggplot(daily_activity, aes(x = activity_level, fill = activity_level)) +
  geom_bar(alpha = 0.8) +
  scale_fill_manual(values = bellabeat_colors) +
  labs(title = "A) Distribución de Niveles de Actividad", x = "", y = "Conteo") +
  theme(legend.position = "none", axis.text.x = element_text(angle = 45, hjust = 1))

p2 <- ggplot(daily_sleep, aes(x = sleep_quality, fill = sleep_quality)) +
  geom_bar(alpha = 0.8) +
  scale_fill_manual(values = c("#E74C3C", "#F39C12", "#27AE60", "#3498DB")) +
  labs(title = "B) Distribución de Calidad de Sueño", x = "", y = "Conteo") +
  theme(legend.position = "none", axis.text.x = element_text(angle = 45, hjust = 1))

p3 <- actividad_semanal %>%
  ggplot(aes(x = weekday, y = promedio_pasos, group = 1)) +
  geom_line(color = bellabeat_colors[1], size = 1.5) +
  geom_point(color = bellabeat_colors[4], size = 3) +
  labs(title = "C) Tendencia Semanal de Pasos", x = "", y = "Pasos Promedio") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

p4 <- ggplot(segment_dist, aes(x = "", y = porcentaje, fill = user_segment)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  scale_fill_manual(values = bellabeat_colors) +
  labs(title = "D) Segmentación de Usuarios") +
  theme_void()

grid.arrange(p1, p2, p3, p4, ncol = 2)


6. FASE ACT: Recomendaciones Estratégicas

6.1 Top 3 Recomendaciones para Estrategia de Marketing

🎯 RECOMENDACIÓN #1: “Movimiento Consciente”

Campaña enfocada en romper el sedentarismo

Estrategia: - Feature Clave: Alertas inteligentes de movimiento cada 60-90 minutos durante el día - Mensaje de Marketing: “Tu cuerpo está diseñado para moverse - nosotros te recordamos hacerlo” - Contenido: Mini-rutinas de 2-5 minutos que se pueden hacer en la oficina/casa - Canal: Notificaciones push personalizadas según el patrón de actividad del usuario

Por qué: El 81% del tiempo diario es sedentario. Esta es la mayor oportunidad de diferenciación.

KPI de Éxito: Reducir tiempo sedentario promedio en 10% en 3 meses.

🎯 RECOMENDACIÓN #2: “Sleep Better, Live Better”

Programa integral de mejora del sueño

Estrategia: - Feature Clave: Coach de sueño con rutinas personalizadas de wind-down - Mensaje de Marketing: “El 50% de las usuarias no duermen lo suficiente. Cambiemos eso juntas” - Contenido: - Recordatorios inteligentes de hora de dormir - Meditaciones guiadas pre-sueño - Tracking de factores que afectan el sueño (cafeína, ejercicio tarde, etc.) - Canal: Email marketing con “Sleep Score” semanal personalizado

Por qué: Solo 50% de los registros muestran sueño en rango óptimo (7-9h).

KPI de Éxito: Incrementar usuarios con 7+ horas de sueño en 20% en 4 meses.

🎯 RECOMENDACIÓN #3: “Consistency Rewards”

Programa de gamificación para adherencia

Estrategia: - Feature Clave: Sistema de streaks, badges y challenges community - Mensaje de Marketing: “Tu salud es un maratón, no un sprint. Celebremos cada día” - Contenido: - Challenges semanales adaptativos al nivel del usuario - Tabla de líderes social (opcional) - Rewards desbloqueables (contenido premium, descuentos tienda) - Canal: In-app engagement + social media campaigns con UGC

Por qué: Variación significativa en días de uso indica problemas de retención.

KPI de Éxito: Aumentar usuarios con 25+ días activos/mes en 30% en 6 meses.

6.2 Recomendaciones Específicas por Producto

Para la App Bellabeat:

  1. Implementar Panel de “Wellness Score” Diario
    • Combina actividad + sueño + hidratación en un score único
    • Educación sobre factores que más impactan el score
  2. Sección de “Insights Personalizados”
    • Basados en los patrones individuales del usuario
    • Ej: “Notas que duermes mejor los días que caminas >8000 pasos”
  3. Integración Social Inteligente
    • Challenges de equipos/amigas
    • Compartir logros sin números (privacidad)

Para Dispositivos (Leaf/Time):

  1. Vibración Inteligente “Move Alert”
    • Basada en ML de patrones sedentarios del usuario
    • No intrusiva pero efectiva
  2. Métricas de Sueño Mejoradas
    • Tracking de calidad (fases REM/profundo)
    • Comparación con baseline personal

Para la Membresía:

  1. Tier “Wellness Coach”
    • Planes personalizados basados en datos
    • Check-ins mensuales con nutricionista/coach
  2. Biblioteca de Contenido Segmentado
    • Para usuarios sedentarios: rutinas de inicio
    • Para usuarios activos: optimización de rendimiento

6.3 Próximos Pasos

Roadmap de Implementación
Fase Accion
Inmediato (0-30 días)
  • Priorizar features de alertas de movimiento
  • Diseñar campaña ‘Sleep Better’
  • Configurar tracking de KPIs
Corto Plazo (1-3 meses)
  • Lanzar beta de ‘Move Alerts’
  • Implementar Sleep Coach en app
  • Iniciar contenido educativo en redes
  • Mediano Plazo (3-6 meses)
    • Lanzar sistema de gamificación completo
  • Analizar primeros resultados y optimizar
  • Expandir biblioteca de contenido
  • Largo Plazo (6-12 meses)
    • Evaluación completa de impacto
  • Nuevas features basadas en feedback
  • Escalar estrategias exitosas
  • 6.4 Métricas de Seguimiento Recomendadas

    Para medir el éxito de las estrategias propuestas:

    Métricas de Engagement: - Daily Active Users (DAU) / Monthly Active Users (MAU) - Session frequency y duration - Retention rate (D1, D7, D30)

    Métricas de Salud/Wellness: - % usuarios alcanzando metas diarias - Reducción en tiempo sedentario promedio - Mejora en horas de sueño promedio - Sleep efficiency score

    Métricas de Negocio: - Conversión a membresía premium - Customer Lifetime Value (CLV) - Net Promoter Score (NPS) - Churn rate


    7. Limitaciones y Consideraciones

    7.1 Limitaciones del Estudio

    1. Tamaño de muestra: Solo 30 usuarios - no generalizable estadísticamente
    2. Antigüedad de datos: Datos de 2016 - comportamientos pueden haber cambiado
    3. Sesgo demográfico: No sabemos género, edad, ubicación geográfica
    4. Competencia: Datos de FitBit, no de Bellabeat
    5. Datos incompletos: Solo 24 usuarios tienen datos de sueño

    7.2 Recomendaciones para Futuros Análisis

    1. Obtener datos propios de Bellabeat
      • Muestra más grande y representativa
      • Datos demográficos completos
      • Tracking de uso de features específicas
    2. Análisis de cohortes
      • Estudiar retención a lo largo del tiempo
      • Identificar factores de churn
    3. Encuestas cualitativas
      • Entender motivaciones y barreras
      • Feedback sobre features deseadas
    4. A/B Testing
      • Probar diferentes estrategias de engagement
      • Optimizar timing y contenido de notificaciones

    8. Conclusiones

    Resumen Ejecutivo

    Este análisis de datos de dispositivos inteligentes de fitness ha revelado insights clave sobre los patrones de uso y comportamiento de los usuarios que pueden informar directamente la estrategia de marketing de Bellabeat:

    Hallazgos Principales:

    1. Crisis de Sedentarismo: Los usuarios pasan >80% del día sedentarios, una oportunidad masiva para intervención
    2. Déficit de Sueño: Solo ~50% de los registros muestran sueño óptimo (7-9h)
    3. Patrones Predecibles: Actividad varía consistentemente por día de semana
    4. Desafíos de Engagement: Variación en uso del dispositivo sugiere necesidad de mejores motivadores

    Impacto en Estrategia Bellabeat:

    Las tres recomendaciones principales - Movimiento Consciente, Sleep Better, y Consistency Rewards - abordan directamente estos hallazgos y posicionan a Bellabeat como líder en wellness holístico para mujeres.

    Al enfocarse en pequeñas acciones diarias en lugar de transformaciones masivas, y al personalizar la experiencia según los patrones individuales, Bellabeat puede diferenciarse en un mercado saturado.

    ## === INFORMACIÓN DE LA SESIÓN ===
    ## R version 4.5.2 (2025-10-31)
    ## Platform: x86_64-pc-linux-gnu
    ## Running under: Ubuntu 24.04.3 LTS
    ## 
    ## Matrix products: default
    ## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
    ## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
    ## 
    ## locale:
    ##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
    ##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
    ##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
    ## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
    ## 
    ## time zone: UTC
    ## tzcode source: system (glibc)
    ## 
    ## attached base packages:
    ## [1] stats     graphics  grDevices utils     datasets  methods   base     
    ## 
    ## other attached packages:
    ##  [1] kableExtra_1.4.0   knitr_1.51         corrplot_0.95      plotly_4.11.0     
    ##  [5] ggpubr_0.6.2       RColorBrewer_1.1-3 viridis_0.6.5      viridisLite_0.4.2 
    ##  [9] gridExtra_2.3      scales_1.4.0       janitor_2.2.1      lubridate_1.9.4   
    ## [13] forcats_1.0.1      stringr_1.6.0      dplyr_1.1.4        purrr_1.2.0       
    ## [17] readr_2.1.6        tidyr_1.3.2        tibble_3.3.0       ggplot2_4.0.1     
    ## [21] tidyverse_2.0.0   
    ## 
    ## loaded via a namespace (and not attached):
    ##  [1] gtable_0.3.6      xfun_0.55         bslib_0.9.0       htmlwidgets_1.6.4
    ##  [5] rstatix_0.7.3     lattice_0.22-7    tzdb_0.5.0        vctrs_0.6.5      
    ##  [9] tools_4.5.2       generics_0.1.4    parallel_4.5.2    pkgconfig_2.0.3  
    ## [13] Matrix_1.7-4      data.table_1.18.0 S7_0.2.1          lifecycle_1.0.4  
    ## [17] compiler_4.5.2    farver_2.1.2      textshaping_1.0.4 carData_3.0-5    
    ## [21] snakecase_0.11.1  htmltools_0.5.9   sass_0.4.10       yaml_2.3.12      
    ## [25] lazyeval_0.2.2    Formula_1.2-5     crayon_1.5.3      pillar_1.11.1    
    ## [29] car_3.1-3         jquerylib_0.1.4   cachem_1.1.0      abind_1.4-8      
    ## [33] nlme_3.1-168      tidyselect_1.2.1  digest_0.6.39     stringi_1.8.7    
    ## [37] splines_4.5.2     labeling_0.4.3    fastmap_1.2.0     grid_4.5.2       
    ## [41] cli_3.6.5         magrittr_2.0.4    broom_1.0.11      withr_3.0.2      
    ## [45] backports_1.5.0   bit64_4.6.0-1     timechange_0.3.0  rmarkdown_2.30   
    ## [49] httr_1.4.7        bit_4.6.0         otel_0.2.0        ggsignif_0.6.4   
    ## [53] hms_1.1.4         evaluate_1.0.5    mgcv_1.9-3        rlang_1.1.6      
    ## [57] glue_1.8.0        xml2_1.5.1        vroom_1.6.7       svglite_2.2.2    
    ## [61] rstudioapi_0.17.1 jsonlite_2.0.0    R6_2.6.1          systemfonts_1.3.1