Este es el caso práctico final de curso de Análisis de Datos de Google. En este estudio de caso, utilizaré los siguientes pasos para el análisis de datos: preguntar, preparar, procesar, analizar, compartir y actuar.
Bellabeat es una empresa de alta tecnología que fabrica productos inteligentes centrados en la salud. La recopilación de datos sobre la actividad física, el sueño, el estrés y la salud reproductora ha permitido a Bellabeat empoderar a las mujeres con conocimientos sobre su propia salud y hábitos. Desde su fundación en 2013, Bellabeat ha crecido rápidamente y se ha posicionado como una empresa de bienestar para las mujeres impulsada por la tecnología.
En el análisis de datos que voy a realizar, analizaré los datos de dispositivos inteligentes para conocer como los clientes los utilizan. Los hallazgos ayudarán a orientar a la estrategia de marketing de la empresa.
Urška Sršen es la cofundadora y directora creativa de Bellabeat.
Sando Mur es el matemático y cofundador de Bellabeat; miembro clave del equipo ejecutivo de Bellabeat.
El equipo de analistas de datos se encarga de recopilar, analizar e informar los datos, ellos ayudan a conducir la estrategia de marketing de Bellabeat.
Aplicación Bellabeat: La aplicación Bellabeat proporciona a los usuarios datos de salud relacionados con su actividad física, sueño, estrés, ciclo menstrual y hábitos de conciencia plena. Estos datos pueden ayudar a los usuarios a comprender sus hábitos actuales y adoptar decisiones saludables. La aplicación Bellabeat se conecta a su línea de productos de bienestar inteligentes.
Leaf: Dispositivo de seguimiento clásico de bienestar de Bellabeat que se puede usar como pulsera, collar o clip. El dispositivo Leaf se conecta a la aplicación Bellabeat para hacer un seguimiento de la actividad física, el sueño y el estrés.
Time: Este reloj de bienestar combina el aspecto intemporal de un reloj clásico con la tecnología inteligente para hacer el seguimiento de la actividad física, el sueño y el estrés del usuario. El reloj Time se conecta a la aplicación Bellabeat para proporcionar información sobre el bienestar diario.
Spring: Es una botella de agua que hace el seguimiento diario del consumo de agua mediante el uso de tecnología inteligente para garantizar la hidratación adecuada a lo largo del día. La botella Spring se conecta a la aplicación Bellabeat para hacer el seguimiento de los niveles de hidratación.
Sršen sabe que un análisis de los datos del consumo disponible en la aplicación Bellabeat revelaría más oportunidades de crecimiento. Le pidió al equipo de análisis de marketing que se centrara en un producto de Bellabeat y analizara los datos de uso de dispositivos inteligentes para obtener información sobre cómo las personas ya usan sus dispositivos inteligentes. Luego, utilizando esta información, le gustaría recibir recomendaciones de alto nivel sobre cómo estas tendencias pueden informar la estrategia de marketing de Bellabeat.
1) ¿Cuáles son algunas tendencias en el uso de dispositivos inteligentes?
2) ¿Cómo podrían aplicarse estas tendencias a los clientes de Bellabeat?
3) ¿Cómo podrían estas tendencias ayudar a influir en la estrategia de marketing de Bellabeat?
Los datos utilizados para este estudio de caso se obtuvieron de FitBit Fitness Tracker Data de Kaggle a través de Amazon Mechanical Turk entre el 12/03/2016 y el 12/05/2016. Este conjunto de datos contiene datos de seguimiento de actividad física personal de 30 usuarios de Fitbit que dieron su consentimiento para el envío de información sobre su actividad diaria, pasos, frecuencia cardíaca y seguimiento del sueño.
¿Los datos son ROCCC1 son confiable, original, completo, actual y citado? Veamos:
Confiable: no hay información adicional sobre género, edad o estilo de vida y solo tiene una muestra de 30 participantes.
Original: los datos provienen de un tercero Amazon Mechanical Turk.
Completo: hay algunos campos a los que les falta información debido a que todos los usuarios no usaron FitBit durante 30 días.
Actual: los datos son de 2016. Podría haber cambios en el estilo de vida desde entonces.
Citado: Desconocido ya que los datos provienen de un tercero.
Debido al gran tamaño de los datos recopilados, usaré R (lenguaje de programación) para realizar este estudio de caso por su capacidad para manejar grandes conjuntos de datos y por nos brindar con una buena visualización de datos. Vamos a por ello:
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(dplyr)
library(ggplot2)
library(janitor)
##
## Attaching package: 'janitor'
##
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
library(ggpubr)
dailyAct <- read.csv("dailyActivity_merged.csv")
sleepDay <- read.csv("sleepDay_merged.csv")
dailySteps <- read.csv("dailySteps_merged.csv")
dailyCal <- read.csv("dailyCalories_merged.csv")
minsSleep <- read.csv("minuteSleep_merged.csv")
dailyAct%>%
glimpse()
## Rows: 940
## Columns: 15
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 150396036…
## $ ActivityDate <chr> "4/12/2016", "4/13/2016", "4/14/2016", "4/15/…
## $ TotalSteps <int> 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 <int> 25, 21, 30, 29, 36, 38, 42, 50, 28, 19, 66, 4…
## $ FairlyActiveMinutes <int> 13, 19, 11, 34, 10, 20, 16, 31, 12, 8, 27, 21…
## $ LightlyActiveMinutes <int> 328, 217, 181, 209, 221, 164, 233, 264, 205, …
## $ SedentaryMinutes <int> 728, 776, 1218, 726, 773, 539, 1149, 775, 818…
## $ Calories <int> 1985, 1797, 1776, 1745, 1863, 1728, 1921, 203…
sleepDay%>%
glimpse()
## 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 <int> 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ TotalMinutesAsleep <int> 327, 384, 412, 340, 700, 304, 360, 325, 361, 430, 2…
## $ TotalTimeInBed <int> 346, 407, 442, 367, 712, 320, 377, 364, 384, 449, 3…
dailySteps%>%
glimpse()
## 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/…
## $ StepTotal <int> 13162, 10735, 10460, 9762, 12669, 9705, 13019, 15506, 1054…
dailyCal%>%
glimpse()
## 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 <int> 1985, 1797, 1776, 1745, 1863, 1728, 1921, 2035, 1786, 1775…
minsSleep%>%
glimpse()
## Rows: 188,521
## Columns: 4
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960366, 1503…
## $ date <chr> "4/12/2016 2:47:30 AM", "4/12/2016 2:48:30 AM", "4/12/2016 2:49:…
## $ value <int> 3, 2, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1…
## $ logId <dbl> 11380564589, 11380564589, 11380564589, 11380564589, 11380564589,…
dailyAct <- dailyAct %>%
rename(Date = ActivityDate) %>%
mutate(Date = as_date(Date, format = "%m/%d/%Y"))
dailyCal <- dailyCal %>%
rename(Date = ActivityDay) %>%
mutate(Date = as_date(Date, format = "%m/%d/%Y"))
dailySteps <- dailySteps %>%
rename(Date = ActivityDay) %>%
mutate(Date = as_date(Date, format = "%m/%d/%Y"))
sleepDay <- sleepDay %>%
rename(Date = SleepDay) %>%
mutate(Date = as_date(Date,format ="%m/%d/%Y %I:%M:%S %p" , tz=Sys.timezone()))
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `Date = as_date(Date, format = "%m/%d/%Y %I:%M:%S %p", tz =
## Sys.timezone())`.
## Caused by warning:
## ! `tz` argument is ignored by `as_date()`
sum(duplicated(dailyAct))
## [1] 0
sum(duplicated(dailySteps))
## [1] 0
sum(duplicated(dailyCal))
## [1] 0
sum(duplicated(minsSleep))
## [1] 543
sum(duplicated(sleepDay))
## [1] 3
minsSleep <- minsSleep %>%
distinct() %>%
drop_na()
sleepDay <- sleepDay %>%
distinct() %>%
drop_na()
sum(duplicated(minsSleep))
## [1] 0
sum(duplicated(sleepDay))
## [1] 0
Ahora que los datos están limpios, empiezo a buscar información inicial a partir de ellos.
allActivity <- merge(dailyAct, sleepDay, by = c("Id", "Date"), all = TRUE)
allActivity <- allActivity %>%
mutate( Weekday = weekdays(as.Date(Date, "%m/%d/%Y")))
View(allActivity)
allActivity$Weekday <- factor(allActivity$Weekday,
levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
View(allActivity)
Intruduciré gráficos rápidos para ver algunas relaciones entre los datos.
Comprobo con qué frecuencia las personas usan su FitBit durante la semana.
A continuación, miro cuál es la relación entre las calorías quemadas y la actividad no sedentaria:
ggplot(data = allActivity, aes(x=TotalSteps + VeryActiveMinutes + LightlyActiveMinutes + FairlyActiveMinutes, y = Calories, color = Calories)) +
scale_color_gradient(low = "yellow", high = "red") +
geom_point() + stat_smooth(method = lm) +
labs(title = "Minutos activos y calorías quemadas", x = "Minutos activos combinados (muy activo + bastante activo + ligeramente activo))")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: colour
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
Ahora elijo centrarme en los patrones de sueño. Aquí comparo el tiempo que los usuarios pasaron en la cama con su tiempo de sueño actual.
ggplot(data = allActivity, aes(x = TotalMinutesAsleep, y = TotalTimeInBed)) +
geom_point()
## Warning: Removed 530 rows containing missing values (`geom_point()`).
Parece que hay algunos usuarios que pasan tiempo en la cama sin estar realmente dormidos. El domingo parece el día en el que la mayoría de usuarios pasan tiempo en la cama sin dormir.
Con estos dos gráficos trazados, quiero ver si existe una correlación entre las calorías quemadas y el tiempo de sueño. Hago una trama para “Tiempo de sueño” frente a “Calorías quemadas”. Y para que sea más fácil de entender el contexto de los minutos, convierto los minutos en horas.
ggplot(data = allActivity, aes(x = Calories, y = TotalMinutesAsleep / 60, color = Calories))+ scale_color_gradient(low = "yellow", high = "red") +
geom_point() +
stat_smooth(method = lm) +
labs(title = "Total de horas en reposo frente a calorías quemadas", y = "Horas de sueño", x = "
Calorías quemadas")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 530 rows containing non-finite values (`stat_smooth()`).
## Warning: The following aesthetics were dropped during statistical transformation: colour
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
## Warning: Removed 530 rows containing missing values (`geom_point()`).
Parece que los usuarios tuvieron un tiempo de sueño promedio sin importar cuántas calorías quemaron, por lo que no hay correlación ahí.
Recopilo algunas ideas para sacar conclusiones para nuestras partes interesadas. Estos gráficos facilitarán la comparación de diferentes tendencias en los datos.
tma <- ggplot(data = allActivity, aes(TotalMinutesAsleep / 60, SedentaryMinutes, color = TotalMinutesAsleep)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red") +
labs(title = "Min sedentarios vs horas de sueño", y = "Minutos sedentarios", x = "Horas de sueño")
ttib <- ggplot(data = allActivity, aes(TotalTimeInBed / 60, SedentaryMinutes, color = TotalTimeInBed)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red") +
labs(title = "Min sedentarios vs horas en la cama", y = "Minutos sedentarios", x = "Horas en la cama")
ggarrange(ttib, tma, ncol = 2, nrow = 1)
## Warning: Removed 530 rows containing missing values (`geom_point()`).
## Removed 530 rows containing missing values (`geom_point()`).
Hay un ligero aumento en la cantidad de usuarios sedentarios que pasan más tiempo despiertos en la cama.
Ahora hago gráficos para ver qué tipos de usuarios de FitBit duermen más.
sms <- ggplot(data = allActivity, aes(TotalMinutesAsleep, SedentaryMinutes, color = TotalMinutesAsleep)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
tss <- ggplot(data = allActivity, aes(TotalMinutesAsleep, TotalSteps, color = TotalMinutesAsleep)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
tds <- ggplot(data = allActivity, aes(TotalMinutesAsleep, TotalDistance, color = TotalMinutesAsleep)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
vas <- ggplot(data = allActivity, aes(TotalMinutesAsleep, VeryActiveMinutes, color = TotalMinutesAsleep)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
ggarrange(sms, tss, tds, vas, ncol = 2, nrow = 2)
## Warning: Removed 530 rows containing missing values (`geom_point()`).
## Removed 530 rows containing missing values (`geom_point()`).
## Removed 530 rows containing missing values (`geom_point()`).
## Removed 530 rows containing missing values (`geom_point()`).
Hago una comparación entre los diferentes tipos de actividades y la cantidad de calorías que queman.
smc <- ggplot(data = allActivity, aes(SedentaryMinutes, Calories, color = Calories)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
tsc <- ggplot(data = allActivity, aes(TotalSteps, Calories, color = Calories)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
tdc <- ggplot(data = allActivity, aes(TotalDistance, Calories, color = Calories)) +
geom_point() +
scale_color_gradient(low = "yellow", high = "red")
vac <- ggplot(data = allActivity, aes(VeryActiveMinutes, Calories, color = Calories)) +
geom_point() + scale_color_gradient(low = "yellow", high = "red")
ggarrange(smc,tsc, tdc, vac, ncol = 2, nrow = 2)
Veamos cómo pasa la gente la mayor parte de su tiempo. Desgloso los minutos de actividad en porcentajes para hacer un gráfico circular.
dataPercent <- allActivity %>%
summarise(sum_fa = sum(FairlyActiveMinutes/1148807*100),
sum_va = sum(VeryActiveMinutes/1148807*100),
sum_la = sum(LightlyActiveMinutes/1148807*100),
sum_se = sum(SedentaryMinutes/1148807*100),
sum_total=sum(VeryActiveMinutes+FairlyActiveMinutes+LightlyActiveMinutes+SedentaryMinutes)) %>%
round(digits = 2)
piechart <- c(dataPercent$sum_va, dataPercent$sum_fa, dataPercent$sum_la, dataPercent$sum_se, dataPercent$sum)
lbls <- c("Muy activo", "Bastante activo", "Ligeramente activo", "Sedentario")
pie(piechart,
labels = paste(lbls, sep =" "),
col = c("purple", "turquoise","yellow", "red"),
main = "Minutos de actividad")
Existe un amplio margen de usuarios sedentarios. Es de esperar un margen mayor, ya que las personas todavía necesitan descansar, pero es desproporcionadamente mayor que los otros tipos de actividades.
Las observaciones y recomendaciones estan basadas en los conocimientos extraídos del análisis entre el 12/03/2016 y el 12/05/2016.
1)Los usuarios de Fitbit no usan su FitBit constantemente:
La aplicación Bellabeat;
Podría tener notificaciones que recuerden a los usuarios que deben usar su dispositivo para tener la mayor precisión de los datos.
Podría tener una función donde los usuarios podrían obtener hitos por el tiempo que llevan en el dispositivo.
Podría agregar una función que permita a los usuarios conectarse con amigos para comparar el tiempo de uso.
2) Los usuarios pasan mucho tiempo sedentarios. La OMS 2 recomiendan 150 ejercicios de actividad física a la semana, lo que equivale aproximadamente a 30 minutos al día
Si un usuario no puede estar activo por algún motivo, tener una función en la aplicación donde pueda decirle a la aplicación que no puede estar activo temporalmente.
Agregar una función a la aplicación donde el usuario pueda indicar sus intereses para que luego la aplicación pueda sugerir actividades como deportes, natación, caminatas, etc.
Configurar los recordatorios si el usuario permanece en modo sedentario durante un período de tiempo prolongado.
3) Los usuarios pasan tiempo en la cama sin dormir. Esto puede deberse al uso del smartphone mientras se están en la cama. La emisión de luz azul mientras se está en la cama puede afectar negativamente a los ciclos del sueño.
La aplicación Bellabeat;
Podría tener una función donde los usuarios puedan ingresar a su hora de acostarse. Así siendo, la aplicación puede rastrear el uso del tiempo de pantalla durante este periodo y enviar notificaciones para recordarles que reduzcan el tiempo de pantalla mientras estén en la cama.
Podría tener una sección donde se publican consejos y datos sobre el sueño para los usuarios que tienen problemas para conciliar el sueño y permanecer dormidos.
¡Muchas gracias!
Valéria Moreira - Publicist | Data analytics - - - - https://www.linkedin.com/in/valériamoreira - - - - morera.valeria@gmail.com - - - - https://sites.google.com/view/valeria-moreira/inicio?authuser=1