As a junior data analyst working on the marketing analytics team at Bellabeat, a high-tech manufacturer of health-focused products for women, my role involves analyzing smart device usage data to uncover trends and insights that can support strategic business decisions.
Bellabeat is a successful small company with a loyal user base. However, it has significant potential to grow and become a major player in the global smart device market. This case study aims to explore how Bellabeat users interact with their health-tracking devices and identify usage patterns that can inform marketing strategies and product development.
The goal of this analysis is to help Bellabeat’s marketing team better understand how consumers use smart devices in their daily lives. By analyzing historical data collected from fitness trackers, we aim to identify trends in activity, sleep, and other health behaviors to support data-driven marketing strategies.
Urška Sršen: Bellabeat’s cofounder and Chief Creative Officer
Sando Mur: Mathematician and Bellabeat’s cofounder; key member of the Bellabeat executive team
Bellabeat is a leading healthcare company focused on women’s health through smart devices. In today’s era, combining fashion with health is a smart move and represents a tremendous market opportunity. The company is now interested in understanding its current market position and user behavior to better target future marketing campaigns.
The Product Bellabeat Used and have potential in market is below :
*Bellabeat app
*Leaf
*Time
*Spring
*Bellabeat Membership
We will take a closer look at each product and its data to determine prospects for the future.
The scenario we should keep in mind is
What are some trends in smart device usage?
How could these trends apply to Bellabeat customers?
How could these trends help influence Bellabeat marketing strategy?
The data source used for our case study is FitBit Fitness Tracker Data. This dataset is stored in Kaggle and was made available through Mobius.
The dataset includes information from 30 individual Fitbit users, recorded over a two-month period. It contains details on their daily activity levels, heart rate, sleep patterns, and other health-related metrics. The data may reflect individual user behavior based on the type of Fitbit device they used and how consistently they tracked their activities.
This project uses public data from Fitbit users, shared on Kaggle. The dataset was originally collected through Amazon Mechanical Turk, with participants voluntarily submitting their activity and health data.
The dataset is freely available for public use, with no personal identifiers. The creator has released the data under a public domain license, making it ethically sound for analysis without requiring consent or special permissions.
The information is spread across 18 CSV files, each focusing on a specific aspect of user behavior (e.g., daily steps, sleep logs, heart rate tracking, weight logs). Each file contains a unique ID per user, and multiple rows per person, reflecting time-based recordings.
To prepare the data for analysis, I utilized both SQL and R, combining the strengths of structured query operations with the flexibility of statistical computing.
NA handling,
interpolation)Using SQL early in the process helped with efficient preprocessing, allowing me to work with only relevant data subsets. This reduced complexity and computation time when working in R.
On the other hand, R was ideal for further wrangling and preparing visual outputs, enabling better storytelling through plots, summaries, and trend visualizations.
Together, these tools helped create a clean and structured dataset, ensuring a solid foundation for the next stage: analysis.
First install Package in Console section in R
install.package(“tidyverse”)
install.package(“DBI”)
install.package(“ggplot2”)
install.package(“dplyr”)
library(tidyverse)
library(DBI)
library(ggplot2)
library(sqldf)
library(dplyr)
library(janitor)
dailyActivity_df <- read.csv("FitData/dailyActivity_merged.csv")
heartrate_second_df <- read.csv("FitData/heartrate_seconds_merged.csv")
hourlyCalories_df <- read.csv("FitData/hourlyCalories_merged.csv")
hourlyIntensities_df <- read.csv("FitData/hourlyIntensities_merged.csv")
hourlySteps_df <- read.csv("FitData/hourlySteps_merged.csv")
minuteCalories_df <- read.csv("FitData/minuteCaloriesNarrow_merged.csv")
minuteIntensities_df <- read.csv("FitData/minuteIntensitiesNarrow_merged.csv")
minuteSleep_df <- read.csv("FitData/minuteSleep_merged.csv")
minuteSteps_df <- read.csv("FitData/minuteStepsNarrow_merged.csv")
weight_df <- read.csv("FitData/weightLogInfo_merged.csv")
str(dailyActivity_df)
## 'data.frame': 457 obs. of 15 variables:
## $ Id : num 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
## $ ActivityDate : chr "3/25/2016" "3/26/2016" "3/27/2016" "3/28/2016" ...
## $ TotalSteps : int 11004 17609 12736 13231 12041 10970 12256 12262 11248 10016 ...
## $ TotalDistance : num 7.11 11.55 8.53 8.93 7.85 ...
## $ TrackerDistance : num 7.11 11.55 8.53 8.93 7.85 ...
## $ LoggedActivitiesDistance: num 0 0 0 0 0 0 0 0 0 0 ...
## $ VeryActiveDistance : num 2.57 6.92 4.66 3.19 2.16 ...
## $ ModeratelyActiveDistance: num 0.46 0.73 0.16 0.79 1.09 ...
## $ LightActiveDistance : num 4.07 3.91 3.71 4.95 4.61 ...
## $ SedentaryActiveDistance : num 0 0 0 0 0 0 0 0 0 0 ...
## $ VeryActiveMinutes : int 33 89 56 39 28 30 33 47 40 15 ...
## $ FairlyActiveMinutes : int 12 17 5 20 28 13 12 21 11 30 ...
## $ LightlyActiveMinutes : int 205 274 268 224 243 223 239 200 244 314 ...
## $ SedentaryMinutes : int 804 588 605 1080 763 1174 820 866 636 655 ...
## $ Calories : int 1819 2154 1944 1932 1886 1820 1889 1868 1843 1850 ...
head(dailyActivity_df)
head(heartrate_second_df)
head(hourlyCalories_df)
head(hourlyIntensities_df)
head(hourlySteps_df)
head(minuteCalories_df)
head(minuteIntensities_df)
head(minuteSleep_df)
head(minuteSteps_df)
head(weight_df)
Unique User
sqldf("SELECT COUNT(DISTINCT Id) FROM dailyActivity_df")
## COUNT(DISTINCT Id)
## 1 35
sqldf("SELECT COUNT(DISTINCT Id) FROM heartrate_second_df")
## COUNT(DISTINCT Id)
## 1 14
sqldf("SELECT COUNT(DISTINCT Id) FROM hourlyCalories_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM hourlyIntensities_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM hourlySteps_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM minuteCalories_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM minuteIntensities_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM minuteSleep_df")
## COUNT(DISTINCT Id)
## 1 23
sqldf("SELECT COUNT(DISTINCT Id) FROM minuteSteps_df")
## COUNT(DISTINCT Id)
## 1 34
sqldf("SELECT COUNT(DISTINCT Id) FROM weight_df")
## COUNT(DISTINCT Id)
## 1 11
Cleaning Duplicate
sqldf("select Id,ActivityDate,count(*) As Count
from dailyActivity_df
group by Id,ActivityDate
Having count(*)>1")
## [1] Id ActivityDate Count
## <0 rows> (or 0-length row.names)
Check Null
sqldf("
SELECT
SUM(CASE WHEN Id = 0 THEN 1 ELSE 0 END)As ID_notNull,
SUM(CASE WHEN Value = 0 THEN 1 ELSE 0 END) AS Value_notNull,
SUM(CASE WHEN TIME IS NULL THEN 1 ELSE 0 END) time_notNull
From heartrate_second_df"
)
## ID_notNull Value_notNull time_notNull
## 1 0 0 0
## ID_zero Date_missing WeightKg_missing BMI_zero
## 1 0 0 0 0
Rename Columns to Merge Later On
Rename columns to ensure consistency across dataframes before merging. This helps avoid errors due to mismatched column names or data types during the join process. For this I am using R to get desired result
dailyActivity_df <- clean_names(dailyActivity_df)
heartrate_second_df <- clean_names(heartrate_second_df)
hourlyCalories_df <- clean_names(hourlyCalories_df)
hourlySteps_df <- clean_names(hourlySteps_df)
minuteCalories_df <- clean_names(minuteCalories_df)
minuteSleep_df <- clean_names(minuteSleep_df)
minuteSteps_df <- clean_names(minuteSteps_df)
weight_df <- clean_names(weight_df)
After cleaning and preparing the data, this phase focuses on analyzing user activity, sleep, and health patterns. The goal is to identify trends and insights that can help Bellabeat understand user behavior and support marketing strategies.
Analyze data in Daily Activity
dailyActivity_df %>%
summarise(avg_steps = mean(total_steps) , avg_colories = mean(calories))
## avg_steps avg_colories
## 1 6546.562 2189.453
dailyActivity_df %>%
summarise(
very_active = mean(very_active_minutes),
lightly_active = mean(lightly_active_minutes),
sedentary = mean(sedentary_minutes)
)
## very_active lightly_active sedentary
## 1 16.62363 170.07 995.2823
ggplot(dailyActivity_df,aes(x= total_steps, y = calories))+
geom_point(alpha = 0.4) +
geom_smooth(method= "lm") +
labs (title = "Total Steps Vs. Calories")
## `geom_smooth()` using formula = 'y ~ x'
## Active User
active_user <- dailyActivity_df %>%
group_by(id) %>%
summarise(avg_steps = mean(total_steps)) %>%
filter(avg_steps > 7500)
Outof all users,15 users walk more than 7,500 steps a day on average. This shows that a portion of users are already active. Bellabeat can target them with fitness challenges and rewards to keep them engaged.
dailyActivity_df %>%
select(very_active_minutes,lightly_active_minutes,sedentary_minutes)%>%
pivot_longer(everything(),names_to = "activity",values_to = "minute") %>%
ggplot(aes(x= activity,y= minute, fill= activity))+
geom_boxplot()+
labs(title = "Distribution of Activity Types", y = "Minutes")