Autor: Diego Pérez Bustamante
Programador, Analista de Datos y KPI.
Versión para analistas de datos: www.kaggle.com/code/diegopbustamante/caso-bellabeat-trabajo-final?kernelSessionId=135554943
La empresa Bellabeat, es fabricante de productos de alta tecnología orientados a la salud de la mujer. La empresa tiene potencial para convertirse en un actor importante en el mercado global de dispositivos inteligentes. Urška Sršen, cofundadora y directora creativa de Bellabeat, cree que analizar los datos de actividad física de los dispositivos inteligentes podría desplegar nuevas oportunidades de negocio para la empresa. Han solicitado un estudio que se concentre en uno de sus productos y analice los datos de los dispositivos inteligentes, para conocer el uso que hacen los consumidores de los mismos.
Lo que descubra ayudará a orientar la estrategia de marketing de la empresa. Se debe presentar el análisis al equipo ejecutivo de Bellabeat junto con recomendaciones para la estrategia de marketing de Bellabeat.
•Aplicación Bellabeat: La aplicación Bellabeat proporciona a las usuarias 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 las usuarias 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 que las usuarias llevan colocados todo el tiempo.
• 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 hace el seguimiento de la actividad física, el sueño y el estrés. 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.
• Membresía de Bellabeat: Bellabeat también ofrece a los usuarios un programa de membresía mediante suscripción. La membresía brinda a los usuarios un acceso 24/7 a una orientación totalmente personalizada sobre nutrición, actividad física, sueño, salud y belleza y conciencia plena según el estilo de vida y las metas del usuario.
El análisis de datos incluye las fases de Preguntar, Preparar, Procesar, Analizar, Compartir y Actuar.
A continuación una descripción muy resumida de cada fase:
Preguntar: Consiste en informarse con la empresa que encarga la tarea. Se trata de identificar cual es el problema concreto que debemos resolver.
Preparar: Debemos organizar los datos, ver donde se guardaran, Y cuales son los tipos de de derechos que hay sobre los datos que utilizaremos.
Procesar: Los datos deben se depurados por ejemplo quitando duplicados o inconsistencias, para que puedan ser analizados sin producir errores..
Análisis: Trabajar sobre determinados conjuntos de datos con el fin de descubrir partrones y realizar predicciones.
Compartir: Realizar presentaciones visuales (gráficos, videos, etc) que sean claros de entender para distintos tipos de personas.
Actuar: Establecer la serie de recomendaciones o conclusiones a las cuales hemos arribado.
La empresa indica que se utilicen datos públicos y señala un conjunto de datos específicos:Datos de seguimiento de actividad física de Fitbit* (CC0: Dominio público, conjunto de datos disponibles a través de Mobius).
Este conjunto de datos se obtiene en Kaggle. Y contiene el seguimiento de la actividad física personal en treinta usuarios de Fitbit. Treinta usuarios elegibles de Fitbit prestaron su consentimiento para el envío de datos personales de seguimiento que incluyen rendimiento de la actividad física en minutos, ritmo cardíaco y monitoreo del sueño. Incluye información sobre la actividad diaria, pasos y ritmo cardíaco que se puede usar para explorar los hábitos de los usuarios.
Este conjunto de datos fue generado por una encuesta enviada entre el 12/3/2016 y 12/5/2016. Treinta y tres usuarios cedieron la información de sus registros de actividad incluyendo actividad física , ritmo cardiaco, peso y monitor del sueño .
Son 31 dias reportados de 33 usuarios.
Licencia CC0: Public Domain
Los datos se almacenan en Google Drive y en disco local
Los datos están en formatos de tablas CVS.
Sesgo de los datos
En los datos no se indica la edad y sexo lo cual para un análisis de actividad física pueden ser datos fundamentales. En los datos (no hay metadata): no se incluyen referencia a la localidad geográfica. Lo cual puede introducir un sesgo de población urbana, semi-urbana o rural.
Los datos provienen del hemisferio norte en los meses de abril y mayo (primavera) . No podemos comparar con la actividad física realizada en otras estaciones.
Tablas provistas desde Kaggle
Ignoro las siguientes tablas:
minuteCaloriesNarrow_merged, minuteCaloriesWide_merged y weightLogInfo_merged.
Por el siguiente motivo:
Por los datos provistos en las tablas a analizar, el dispositivo que utilizan los usuarios miden:
Debido al pequeño tamaño de las muestras no se pueden analizar las tablas de peso (8 usuarios reportaron) y ritmo cardiaco (7 usuarios) .Recordar que el tamaño mínimo de una muestra estadística es 30.
Por lo anterior y con el objetivo de resolver el problema planteado utilizare las siguientes tablas:
Integridad de los datos
Debido a la limitación del tamaño de la muestra (30 usuarios) y no tener información demografica es posible encontrar un desfazaje entre los resultados esperados y los encontrados.
La visualización de los datos en Kaggle de la tabla principal dailyActivity_merged y otras, muestra al campo TotalDistance (y otros campos) como un valor continuo , por ejemplo 0.259999990463257. La importación de esos datos (desde CVS) a Excel (via Power Query) o Google Sheet los muestra como 259.999.990.463.257.En algunas columnas los importa correctamente y en otras no. Libre Office (Calc) lo importa corretamente.
El problema es de codificación interna (encoding). Power Query lo pre-visualiza con el encode Unicode-Windows y Libre Office lo pre-visualiza como UTF-8. Desde Power Query selecciono UTF-8 y sigue importandolos con el error. Desde Rstudio se importa correctamente.
En Rstudio se importa directamente sin problemas. Por este motivo y otros (algunas tablas tienen mas filas que las soportadas por hojas de cálculo), para el análisis decido utilizar el lenguaje R a través de RStudio. También porque es más rápida la transición codificación – representación visual que hacer el análisis con SQL.
Los traductores automáticos
Los traductores automáticos son geniales salvo cuando traducen lo que no queremos que traduzcan. En RStudio, al importar la tablas necesarias desde los archivos CVS de Kaggle, traduce al español los nombres de las tablas y los títulos de las columnas. Podría pensar que una solución es trabajar con todo el entorno en inglés pero el separador decimal pasaría a ser el punto (.) . Prefiero que cambie los encabezados de cada tabla a español porque voy a presentar el trabajo en castellano. Por lo que de aquí en adelante se veran todos los encabezados (y sus referencias) de las columnas en español.
Instalando paquetes
Instalo los paquetes que utilizare para el análisis. :
Importo las tablas que utilizare en el análisis.
Eliminación de duplicados
Quitando duplicados
Calculos cuantos duplicados hay por tabla.
sum(duplicated(daily_activity))
sum(duplicated(daily_sleep))
sum(duplicated(hourly_steps))
Borro los duplicados
daily_activity <- daily_activity %>% distinct() %>% drop_na()
daily_sleep <- daily_sleep %>% distinct() %>% drop_na()
hourly_steps <- hourly_steps %>% distinct() %>% drop_na()
Se analizaran:
En la tabla Daily_activity (en adelante ActividadDiaria) tenemos 4 tipos de actividad: very, fairly, ligthly y sedentary. De los cuales, la actividad física corresponde a los 3 primeros.
Si en un solo registro sumamos los valores de las 4 variables da como resultado un tiempo aproximado a las 24 horas. De las cuales sedentary corresponde a un interrvalo de tiempo que va de 5 a 8 horas, por lo que sedentario corresponde al tiempo de descanso nocturno.
Genero una tabla llamada TypeActive, extrayendo información de la tabla tipos_actividad, Agrupo por ID, por lo que los siguientes datos corresponderán a cada persona. Quito los valores nulos.
TypeActive <- tipos_actividad %>% drop_na() %>% group_by(Id) %>% summarize(MuyActivos= sum(VeryActiveMinutes), BastanteActivos = sum(FairlyActiveMinutes), PocoActivos = sum(LightlyActiveMinutes))
La tabla la creo con las columnas:
MuyActivos que corresponde a la suma de todos los minutos VeryActiveMinutes.
BastanteActivos que corresponde a la suma de todos los minutos FairlyActiveMinutes.
PocoActivos que corresponde a la suma de todos los minutos LightlyActiveMinutes
Calculo el total de tiempo dedicado a cada tipo de actividad .
Creo las variables TotalMuyActivos, TotalBastanteActivos y TotalPocoActivos.
De la tabla TypeActive sumo la columna MuyActivos y el resultado lo asigno a la variable TotalMuyActivos.
TotalMuyActivos <- TypeActive %>% summarize(sum(MuyActivos))
Hago lo mismo con las otras columnas.
TotalBastanteActivos <- TypeActive %>% summarize(sum(BastanteActivos))
TotalPocoActivos <- TypeActive %>% summarize(Poco activos= sum(PocoActivos))
Obtengo 3 valores :
TotalMuyActivos , TotalBastanteActivos, TotalPocoActivos
Hago una tabla llamada Actividad con estos valores.
Actividad <- c("ActividadTotal")
MinsTotales <- c(TotalMuyActivos, TotalBastanteActivos, TotalPocoActivos)
Total_Mins_Actividad <- data.frame(Actividad, MinsTotales)
Corrigo los encabezados de las columnas:
TotalMuyActivos <- TypeActive %>% summarize("Muy activos" = sum(MuyActivos))
TotalBastanteActivos <- TypeActive %>% summarize("Bastante activos" = sum(BastanteActivos))
TotalPocoActivos <- TypeActive %>% summarize("Poco activos" = sum(PocoActivos))
Creo nuevamente la tabla
MinsTotales <- c(TotalMuyActivos, TotalBastanteActivos, TotalPocoActivos)
Total_Mins_Actividad <- data.frame(Actividad, MinsTotales)
Hago gráfico de sectores:
Tiempo en minutos.
Cada usuario tiene tres comportamientos durante el día : muy activo, bastante activo y poco activo. Si sumamos los comportamientos nos da como resultado que el comportamiento mas común a todos los usuarios es el de poco activos .
La cantidad de pasos diarios es un factor fundamental para determinar el grado de actividad física de una persona común.
Pero no es el único por ejemplo , una persona puede dar muy pocos pasos diarios e ir a nadar y hacer 20 piletas o ir al gimnasio, etc . No debe ser el único factor a considerar ya que introduciría un sesgo de exclusión de otros tipos de actividad física. En este análisis el dispositivo analizado solo puede medir los pasos dados y la distancia recorrida.
Creo una tabla donde agrupo por persona (Id), y sumo el total de pasos.
PasosDiarios <- actividad_diaria %>% drop_na() %>% group_by(Id) %>% summarize(TotalPasosDiarios = sum(TotalSteps)) %>% print(n = 24)
24 usuarios reportaron la información de pasos diarios.
Vista en ventana grafica y en consola dentro de RStudio:
Creo una nueva columna PasosPorDia:
mutate(PasosDiarios, PasosPorDia = TotalPasosDiarios / 24)
Divido por 24 porque fue el mayor numero de días que los usuarios reportaron datos.
Si no asigno la orden mutate a la propia tabla solo vere el resultado en la consola pero el mismo no quedará almacenado. Comportamiento de R, que agrega una columna en memoria para ver una nueva columna sin almacenarla.
Corrijo!
PasosDiarios <- mutate(PasosDiarios, PasosPorDia = TotalPasosDiarios / 27)
Grafico el total de pasos diarios dados por cada persona. Cada punto de color representa a una persona. Son 24 personas las que han reportado datos.
ggplot(data = PasosDiarios) + geom_point( mapping = aes(x = Id, y= PasosPorDia, color= Id))
Agrego una columna para simplificar los Ids que aparecen como potencias de e.
PasosDiarios$ID = c(1:33)
Grafico con el nuevo ID:
ggplot(data = PasosDiarios) + geom_point( mapping = aes(x = ID, y= PasosPorDia, color= ID))
Búsqueda de tendencia:
ggplot(data = PasosDiarios) + geom_smooth(mapping = aes(x = ID, y= PasosPorDia)) + geom_point(mapping = aes(x = ID, y= PasosPorDia, color= ID))
La línea de tendencia indica que la mayoría de usuarios se encuentra en la categoría de algo activos.
En los datos suministrados no hay información demográfica para conocer información detallada como edad, peso, sexo, etc.
Podemos clasificar a los usuarios considerando las cantidad de pasos diarios lo cual es un procedimiento utilizado ampliamente de la siguiente manera: :
Fuente: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6985624/
Genero tabla:
Genero gráfico:
Creo una tabla fecha_distancia seleccionando Id, Fecha de actividad y la distancia total recorrida.
fecha_distancia <- actividad_diaria %>% select(Id, ActivityDate, TotalDistance) %>% drop_na()
Agrego una columna para mostrar el día de la semana
fecha_distancia <- mutate(fecha_distancia, Dia_Semana = format(as.Date(ActivityDate),"%A"))
Grafico con un gráfico de dispersión la distancia recorrida en función del día de la semana para cada participante. Cada punto de un color representa la distancia recorrida por un mismo participante cada día de la semana durante todo el periodo. Por cada día hbrán aprox. 8 puntos del mismo color.
ggplot(data = fecha_distancia) + geom_point(mapping = aes(x = format(as.Date(ActivityDate),"%A"), y= TotalDistance , color= Id))
El limite promedio de distancia máxima recorrido por día fue de 10 km . La distancia más recorrida con frecuencia es de 4 a 6 km. Los días mas activos son los sábados y los miércoles. El día menos activo es el domingo.
De la tabla dormir agrupo por ID y resumo el promedio del total de horas dormidas.
dormir %>% drop_na() %>% group_by(Id) %>% summarize(mean(TotalHorasDormidas)) %>% print(n = 24)
De la tabla dormir, grafico el total de horas dormidas en función de fecha registrada (SleepDay) y del Id.
ggplot(data = dormir) + geom_point(mapping = aes(x = SleepDay, y= TotalHorasDormidas, color=Id))
Total de horas dormidas
ggplot(data = HorasPromDormidas) + geom_point(mapping = aes(x = ID, y= TotalHsDormidas))
Tendencia de total de horas dormidas
ggplot(data = HorasPromDormidas) + geom_smooth(mapping = aes(x = ID, y= TotalHsDormidas))+geom_point(mapping = aes(x = ID, y= TotalHsDormidas))
Tendencia: Los usuarios tienden a dormir entre 6 y 7 horas.
Agrego una columna para simplificar los Ids.
HorasPromDormidas$ID = c(1:24)
Grafico fecha de registro y horas en la cama sin dormir.
ggplot(data = HorasSinDormir) + geom_point( mapping = aes(x = ID, y= HsSinDormir, color= ID))
Tendencia de horas sin dormir
ggplot(data = HorasSinDormir) + geom_smooth(mapping = aes(x = ID, y= HsSinDormir))+geom_point(mapping = aes(x = ID, y= HsSinDormir))
Tendencia: Los usuarios estan de 30 a 60 minutos despiertos antes de dormirse.
“Muy buen trabajdo. Resulta muy motivador ver algo complicado bien explicado".
Mario Leccini,
Montevideo, Uruguay.
“Excelente análisis del proyecto del curso online de analista de datos. Gracias por compartir".
Henry Villegas,
Miami, Estados Unidos.
“Muy buen curso online y mejor proyecto final".
Leticia Oribe,
Los Angeles, Estados Unidos.
“Muy bien explicado y en castellano! Me servirá de guía para subir mi portafolio a Kaggle. Muchas gracias. ".
Raúl Espert,
Madrid, España.