Bellabeat es una compañía en busca de crecimiento y nuevas oportunidades que desarrolla productos tecnológicos enfocados en la salud para mujeres. Cuentan con diferentes productos para el registro de actividad de salud, junto con una aplicación. El propósito de este case study es encontrar tendencias que permitan entregar recomendaciones para las estrategias de marketing, a través del análisis del uso de dispositivos tecnológicos enfocados en el bienestar.
Time: Combina el aspecto de un reloj clásico con tecnología inteligente para rastrear al usuario conectándose mediante la app.
Se analizará el dataset de Fitbit, que contiene la información de rastreo de 33 usuarios, compilando datos como pasos diarios, minutos de sueño y cantidad de calorías, categorizadas de forma diaria o por hora. Específicamente los archivos que se utilizarán son los siguientes
Las herramientas que se utilizarán para llevar a cabo el análisis son
El análisis se dividirá principalmente en dos partes
En primer lugar se analizaron los datos de forma general en Excel.
Los archivos hourlyCalories_merged, hourlyIntensities_merged y
hourlySteps_merged fueron unidos en un solo documento llamado
“Con_Datos_Hora.xlsx” ,la columna AtivityHour se separó en fecha.
Instalación de paquetes
install.packages("tidyverse")
library(tidyverse)
install.packages("janitor")
library(janitor)
install.packages("readxl")
library(readxl)
install.packages("gridExtra")
library(gridExtra)
Lectura de datos
daily <- read_csv('dailyActivity_merged.csv',show_col_types = FALSE)
hourly <- read_excel("Con_Datos_Hora.xlsx", sheet = 1)
sleep <- read_csv('sleepDay_merged.csv',show_col_types = FALSE)
Verificacion y eliminación de duplicados
sum(duplicated(hourly))
## [1] 0
sum(duplicated(daily))
## [1] 0
sum(duplicated(sleep))
## [1] 3
Existen 3 duplicados por lo que serán eliminados
sleep <- sleep[!duplicated(sleep),]
Se comprueba que efectivamente fueron eliminados
sum(duplicated(sleep))
## [1] 0
Cambio de nombres de columnas y eliminación de NULLS
Se ajustan los nombres de las columnas para que cumplan con el estándar
daily <- clean_names(daily) %>%
remove_empty(which = c("rows")) %>%
remove_empty(which = c("cols"))
sleep <- clean_names(sleep) %>%
remove_empty(which = c("rows")) %>%
remove_empty(which = c("cols"))
hourly <- clean_names(hourly)%>%
remove_empty(which = c("rows")) %>%
remove_empty(which = c("cols"))
colnames(sleep)[2] <- "fecha"
colnames(daily)[2] <- "fecha"
Verificacion formato de datos
str(hourly)
## tibble [22,099 × 9] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:22099] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
## $ fecha : POSIXct[1:22099], format: "2016-04-12" "2016-04-12" ...
## $ hora12 : chr [1:22099] "12:00:00 AM" "01:00:00 AM" "02:00:00 AM" "03:00:00 AM" ...
## $ hora24 : chr [1:22099] "00:00:00" "01:00:00" "02:00:00" "03:00:00" ...
## $ step_total : num [1:22099] 373 160 151 0 0 ...
## $ calories : num [1:22099] 81 61 59 47 48 48 48 47 68 141 ...
## $ total_intensity : num [1:22099] 20 8 7 0 0 0 0 0 13 30 ...
## $ average_intensity: num [1:22099] 333333 133333 116667 0 0 ...
## $ activity_hour : chr [1:22099] "4/12/2016 12:00:00 AM" "4/12/2016 1:00:00 AM" "4/12/2016 2:00:00 AM" "4/12/2016 3:00:00 AM" ...
str(daily)
## tibble [940 × 15] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:940] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
## $ fecha : chr [1:940] "4/12/2016" "4/13/2016" "4/14/2016" "4/15/2016" ...
## $ total_steps : num [1:940] 13162 10735 10460 9762 12669 ...
## $ total_distance : num [1:940] 8.5 6.97 6.74 6.28 8.16 ...
## $ tracker_distance : num [1:940] 8.5 6.97 6.74 6.28 8.16 ...
## $ logged_activities_distance: num [1:940] 0 0 0 0 0 0 0 0 0 0 ...
## $ very_active_distance : num [1:940] 1.88 1.57 2.44 2.14 2.71 ...
## $ moderately_active_distance: num [1:940] 0.55 0.69 0.4 1.26 0.41 ...
## $ light_active_distance : num [1:940] 6.06 4.71 3.91 2.83 5.04 ...
## $ sedentary_active_distance : num [1:940] 0 0 0 0 0 0 0 0 0 0 ...
## $ very_active_minutes : num [1:940] 25 21 30 29 36 38 42 50 28 19 ...
## $ fairly_active_minutes : num [1:940] 13 19 11 34 10 20 16 31 12 8 ...
## $ lightly_active_minutes : num [1:940] 328 217 181 209 221 164 233 264 205 211 ...
## $ sedentary_minutes : num [1:940] 728 776 1218 726 773 ...
## $ calories : num [1:940] 1985 1797 1776 1745 1863 ...
str(sleep)
## tibble [410 × 5] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:410] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
## $ fecha : chr [1:410] "4/12/2016 12:00:00 AM" "4/13/2016 12:00:00 AM" "4/15/2016 12:00:00 AM" "4/16/2016 12:00:00 AM" ...
## $ total_sleep_records : num [1:410] 1 2 1 2 1 1 1 1 1 1 ...
## $ total_minutes_asleep: num [1:410] 327 384 412 340 700 304 360 325 361 430 ...
## $ total_time_in_bed : num [1:410] 346 407 442 367 712 320 377 364 384 449 ...
Cambio de formato
daily$fecha <- as.Date(daily$fecha,"%m/%d/%Y")
sleep$fecha <- as.Date(sleep$fecha,"%m/%d/%Y")
Primero se combinarán los datos diarios (daily) con los datos de los habitos del sueño (sleep)
combined_daily_sleep <- merge(daily,sleep,
by= c("id","fecha"))
Para apreciar mejor la relación limitaremos el margen de valores usando el método del rango intercuartílico (IQR), permitiendo incrementar el grado de confianza al eliminar los datos atípicos.
Q1_steps <- quantile(combined_daily_sleep$total_steps, 0.25)
Q3_steps <- quantile(combined_daily_sleep$total_steps, 0.75)
Q1_sleep <- quantile(combined_daily_sleep$total_minutes_asleep, 0.25)
Q3_sleep <- quantile(combined_daily_sleep$total_minutes_asleep, 0.75)
IQR_steps <- Q3_steps - Q1_steps
IQR_sleep <- Q3_sleep - Q1_sleep
lim_sup_steps <- Q3_steps + 1.5*IQR_steps
lim_inf_sleep <- Q1_sleep - 1.5*IQR_sleep
lim_sup_sleep <- Q3_sleep + 1.5*IQR_sleep
Ahora graficaremos en torno a los limites obtenidos, además se destacará el rango más saludable de minutos diarios por dormir de acuerdo a la OMS, correspondientes a entre 7 a 8 horas, y se encontrará el porcentaje de días que cumplen con esta condición
dias_oms <- combined_daily_sleep %>%
filter(total_minutes_asleep >= 420 & total_minutes_asleep <= 480)
pct_dias_oms <-count(dias_oms)*100/count(combined_daily_sleep)
count(dias_oms)
## n
## 1 115
round(pct_dias_oms)
## n
## 1 28
promedio_pasos_oms <- combined_daily_sleep %>%
filter(total_minutes_asleep >= 420 & total_minutes_asleep <= 480) %>%
summarize(promedio_pasos_oms = mean(total_steps))
round(promedio_pasos_oms)
## promedio_pasos_oms
## 1 8493
Grafica
combined_daily_sleep%>%
filter(total_steps < lim_sup_steps) %>%
filter(total_minutes_asleep >lim_inf_sleep & total_minutes_asleep < lim_sup_sleep) %>%
ggplot(aes(x=total_minutes_asleep ,y=total_steps) ) +
geom_smooth()+
geom_point()+
annotate("rect", xmin=420, xmax = 480,ymin=0, ymax=18000,
alpha= .2, fill="green")+
annotate("text", x = 450, y = 18500,
label = "Recomendación OMS", hjust = "center", size = 3)+
labs(x= "Minutos dormido",y= "Pasos totales")+
ggtitle("Relación entre pasos totales y minutos dormido")
Parece haber una relación negativa entre los pasos totales. Mientras más pasos dieron, menos minutos durmieron. Solo el 28% de los días (115) están dentro del rango saludable de horas diarias por dormir de acuerdo a las recomendaciones de la OMS. Entre estos la cantidad de pasos por día en promedio fue de 8493.
Definiremos el retraso al dormir como la cantidad de minutos que pasa el usuario en la cama sin dormir. Añadiremos una columna que muestre la diferencia entre los minutos que el usuario pasa en la cama y los minutos que pasa durmiendo
combined_daily_sleep<- mutate(combined_daily_sleep,
min_despierto = total_time_in_bed - total_minutes_asleep)
Ahora calcularemos el tiempo promedio de retraso al dormir de los usuarios
mean(sleep$total_time_in_bed-sleep$total_minutes_asleep)
## [1] 39.30976
Para graficarlo, al igual que en el paso anterior, usaremos el método del IQR
Q1_min_desp <- quantile(combined_daily_sleep$min_despierto, 0.25)
Q3_min_desp <- quantile(combined_daily_sleep$min_despierto, 0.75)
IQR_min_desp <- Q3_min_desp - Q1_min_desp
lim_sup_min_desp <- Q3_min_desp + 1.5*IQR_min_desp
Ahora graficamos
combined_daily_sleep%>%
filter(total_steps < lim_sup_steps) %>%
filter(min_despierto < lim_sup_min_desp) %>%
ggplot(aes(x=min_despierto ,y=total_steps) ) +
geom_smooth()+
geom_point()+
labs(x= "Retraso al dormir (Min despierto)",y= "Pasos totales")+
ggtitle("Relacion entre pasos totales y retraso al dormir")
No se genera una linea de tendencia clara. Al parecer no existe una correlación directa entre la cantidad de pasos diarios y los minutos de retraso de los usuarios para dormir.
Ahora se analizará la cantidad de pasos promedio de los días en los que personas tuvieron un mayor retraso al dormir, considerando aquellos que sean superiores al límite superior calculado mediante el IQR:
dias_retraso_max <- combined_daily_sleep %>%
filter(min_despierto>lim_sup_min_desp)
count(dias_retraso_max)
## n
## 1 37
promedio_pasos_retraso <- combined_daily_sleep %>%
filter(min_despierto>lim_sup_min_desp) %>%
summarize(promedio_pasos_retraso = mean(total_steps))
round(promedio_pasos_retraso)
## promedio_pasos_retraso
## 1 9558
lim_sup_min_desp
## 75%
## 74.5
cuenta <- combined_daily_sleep %>%
mutate(steps_group = cut(total_steps, breaks = c(0, 5500, 11000, 16500, 22000),
labels = c("0-5500", "5500-11000", "11000-16500", "16500-22000"))) %>%
group_by(steps_group) %>%
summarize(mayor_al_lim = sum(min_despierto > lim_sup_min_desp))
cuenta <- setNames(cuenta, c("Pasos", "Cantidad de dias"))
cuenta <- cuenta %>%
slice(-5)
ggplot(cuenta, aes(x = "", y = `Cantidad de dias`, fill = Pasos)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
scale_fill_manual(values = c("#B0D1B1", "#47944E", "#24693D", "#C1D5D2")) +
labs(x = NULL, y = NULL, fill = "Pasos") +
geom_text(aes(label = `Cantidad de dias`), position = position_stack(vjust = 0.3)) +
ggtitle("Cantidad de pasos dados en días críticos") +
theme_void()
Hubieron 37 días en los que alguna persona sobrepasó el limite superior de los minutos de retraso al dormir típicos de la muestra (74,5 minutos). En promedio, la cantidad de pasos dada durante esos dias es de 9558, y en la mayoria de estos dias se caminaron entre 11000 y 16500 pasos.
Por ultimo relacionaremos mediante una grafica los días de la semana (De domingo a lunes) con los minutos de retraso al dormir y los pasos dados.
dormir_pasos_combinado <- mutate(combined_daily_sleep,
dia = wday(fecha, label = TRUE))
resumen_dormir <- dormir_pasos_combinado %>%
group_by(dia) %>%
summarise(pasos_diarios_promedio = mean(total_steps),
min_despierto_promedio = mean(min_despierto))
g1<- ggplot(data=resumen_dormir, mapping=aes(x=dia,y=min_despierto_promedio))+
geom_col(fill="#80CBC4")+ labs(title="Cantidad diaria promedio de minutos despierto en la cama",
x="Día",y="Minutos despierto en la cama")
g2 <- ggplot(data=resumen_dormir, mapping=aes(x=dia,y=pasos_diarios_promedio))+
geom_col(fill="#00796B")+ labs(title="Cantidad diaria promedio de pasos",
x="Día",y="Pasos diarios")
grid.arrange(g1, g2, ncol = 1)
resumen_dormir
## # A tibble: 7 × 3
## dia pasos_diarios_promedio min_despierto_promedio
## <ord> <dbl> <dbl>
## 1 "dom\\." 7298. 50.8
## 2 "lun\\." 9273. 37.8
## 3 "mar\\." 9183. 38.8
## 4 "mié\\." 8023. 35.3
## 5 "jue\\." 8184. 33.6
## 6 "vie\\." 7901. 39.6
## 7 "sáb\\." 9871. 40.8
El día en el que menos pasos se dan en promedio (7298) es el domingo, coincidentemente, es en el que existe un mayor retraso a la hora de dormir (50,8 minutos)
Primero se graficará la relación entre la hora del día y la cantidad de pasos dados:
hourly$hora_corta <- substr(hourly$hora24, 1, 5)
ggplot(data=hourly) +
geom_point(mapping = aes(x = hora_corta, y = step_total), color = "#2F6790") +
labs(title = "Relación entre la cantidad de pasos y la hora", x = "Hora", y = "Cantidad de pasos") +
xlab("Hora del día") + ylab("Cantidad de pasos")+
theme(axis.text.x = element_text(angle = 45))
Podemos notar que la mayor cantidad de pasos se concentra entre las 08:00hrs. y 19:00hrs. Para un mejor análisis promediaremos los pasos y los relacionaremos a la hora del día en el que se dieron:
pasos_prom_hora <- hourly %>%
group_by(hora_corta) %>%
summarize(pasos_prom = mean(step_total))
pasos_prom_hora
## # A tibble: 24 × 2
## hora_corta pasos_prom
## <chr> <dbl>
## 1 00:00 42.2
## 2 01:00 23.1
## 3 02:00 17.1
## 4 03:00 6.43
## 5 04:00 12.7
## 6 05:00 43.9
## 7 06:00 179.
## 8 07:00 306.
## 9 08:00 428.
## 10 09:00 433.
## # … with 14 more rows
Mediante un grafico los datos se aprecian de la siguiente manera:
ggplot(pasos_prom_hora, aes(hora_corta, pasos_prom, group=1)) +
geom_line(linewidth=0.8) +
labs(title = "Relación entre la cantidad de pasos promedio y la hora", x = "Hora", y = "Pasos promedio") +
xlab("Hora del día") + ylab("Cantidad de pasos promedio")+
theme(axis.text.x = element_text(angle = 90)) +
annotate("rect", xmin = "00:00", xmax = "07:00",
fill = "orange",ymin = 0, ymax = 700, alpha = .1) +
annotate("rect", xmin = "07:00", xmax = "13:00",
fill = "yellow",ymin = 0, ymax = 700, alpha = .1) +
annotate("rect", xmin = "13:00", xmax = "19:00",
fill = "purple",ymin = 0, ymax = 700, alpha = .1) +
annotate("rect", xmin = "19:00", xmax = "23:00",
fill = "blue",ymin = 0, ymax = 700, alpha = .1) +
annotate("text", x = 19.5, y = 640,
label = "Max≈ 600 pasos", hjust = "center", size = 3)+
annotate("text", x = 3.5, y = 100,
label = "Min≈ 6 pasos", hjust = "center", size = 3)+
annotate("text", x = 04, y = 740,
label = "Madrugada", hjust = "center", size = 4)+
annotate("text", x = 11, y = 740,
label = "Día", hjust = "center", size = 4)+
annotate("text", x = 17, y = 740,
label = "Tarde", hjust = "center", size = 4)+
annotate("text", x = 22, y = 740,
label = "Noche", hjust = "center", size = 4)
pasos_prom_hora %>%
filter(pasos_prom == max(pasos_prom))
## # A tibble: 1 × 2
## hora_corta pasos_prom
## <chr> <dbl>
## 1 18:00 599.
pasos_prom_hora %>%
filter(pasos_prom == min(pasos_prom))
## # A tibble: 1 × 2
## hora_corta pasos_prom
## <chr> <dbl>
## 1 03:00 6.43
La hora en la que se dan más pasos promedios (599) es a las 6pm, y la donde se dan menos pasos promedio (6) es a las 3AM. El momento del dia durante el cual se dan en promedio mas pasos es la tarde y donde menos se dan es en la madrugada.
Para finalizar el análisis graficaremos la relación entre la cantidad de pasos promedio diarios con el día de la semana
hourly <- hourly %>%
mutate(momento = case_when(
hora24 %in% c("00:00:00", "01:00:00", "02:00:00","03:00:00","04:00:00","05:00:00","06:00:00") ~ "Madrugada",
hora24 %in% c("07:00:00", "08:00:00", "09:00:00","10:00:00","11:00:00","12:00:00") ~ "Dia",
hora24 %in% c("13:00:00", "14:00:00", "15:00:00","16:00:00","17:00:00","18:00:00") ~ "Tarde",
hora24 %in% c("19:00:00", "20:00:00", "21:00:00","22:00:00","23:00:00") ~ "Noche",
TRUE ~ "otros"))
dia <- hourly %>%
mutate(fecha,
dia = wday(fecha, label = TRUE))
promedios <- aggregate(step_total ~ dia + momento, data=dia, FUN=mean)
promedios$momento <- factor(promedios$momento,
levels = c("Noche", "Tarde", "Dia", "Madrugada"),
ordered = TRUE)
ggplot(promedios, aes(x = dia, y = step_total, fill = momento)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_manual(values = c("#325F8C", "#8E6189", "#F4D166","#F6A245"))+
labs(x = "Día de la semana", y = "Cantidad de pasos", fill = "Momento del día")
Visualmente podemos notar que la cantidad de pasos en relacion al momento del día se mantiene bastante constante, en todos los dias de la semana el momento en el que menos se camina es en la madrugada, y en el que mas se camina en la tarde.
-Promover e informar a los usuarios la importancia del equilibrio entre la actividad física y el descanso. Aunque caminar y mantenerse activo es esencial para la salud, también es fundamental dormir lo suficiente para permitir que el cuerpo se recupere y se repare. Se debe fomentar un enfoque equilibrado para la actividad física y el sueño.
-Se podria promover la actividad física en los domingos, ya que es el día en el que se dan menos pasos. Por ejemplo, podrían crear desafíos o incentivos para animar a los usuarios a moverse más y ver además si esto tiene un impacto positivo en disminuir el mayor retraso al dormir que tuvieron los usuarios en este día.
-Dado que el análisis muestra que los usuarios caminan más en la tarde, se podría incentivar a los usuarios a ser más activos en otros momentos del día. Por ejemplo, podrían ofrecer recordatorios o desafíos para animar a los usuarios a caminar más por la mañana o después de el almuerzo.