← Back to Data
🌿
bellabeat
case study data analysis
Date: 4 Sep 2024

How Can a Wellness Technology Company Play It Smart?

Read the full case study ↗

Introduction

Bellabeat is a wellness-tech company that designs health-focused smart products for women. This case study looks at how the brand could sharpen its marketing strategy by analyzing activity-tracking data from a comparable fitness device, uncovering usage patterns that point toward where Bellabeat's growth opportunity really lies.

Phase 1 - Ask

What is the problem you are trying to solve?

I am solving for business growth via marketing strategy based on the insights from analyzing non-Bellabeat product tracking data.

Phase 2 - Prepare

Where is your data stored?

The data is stored within the Posit Cloud Library

How is the data organized? Is it in a long or wide format?

The datasets are in general long format.

Are there issues with the bias or credibility of this data? Does your data ROCCC?

The data has its limitations owning to the collection date of the data and a few missing data points that are integral to solving the problem at hand. Although the data is from a credible source given the description and upon inspection, there are inconsistencies with it, like the number of participants is more than 30 as opposed to what is listed on the source.

How are you addressing licensing, privacy, security, and accessibility?

Licensing — CC0: Public Domain Accessibility — Easily (https://zenodo.org/record/53894#.X9oeh3Uzaao)

How did you verify the data’s integrity?

I Researched the author and the website provided on Kaggle (https://zenodo.org/record/53894#.X9oeh3Uzaao), then checked the data by importing it into Google Sheets and inspecting basic checks like blanks and unique number of IDs, thus able to find loopholes within it.

Are there any problems with the data?

Yes, there is no demographic bifurcation. As our product is women-centric, it makes sense to give importance to gender. Missing IDs within datasets, meaning inconsistent data.

Phase 3 - Process

What tools are you choosing and why?

I will be using Google Sheets for initial data screening for blanks and duplicates. I have used R for my data analysis process.

What steps have you taken to ensure that the data is clean?

I have checked the data using filters on google sheets, and any inconsistencies within the datasets. And rectified the data accordingly.

What steps have you taken to ensure that the data is clean?

I have checked the data using filters on google sheets, and any inconsistencies within the datasets. And rectified the data accordingly. After inspecting unique IDs using vlookup on multiple datasets, understood that 34 IDs are common within the majority of datasets.

Phase 4 - Analyze

My aim would be to create personas for the marketing team so that they can identify who they would be targeting in their campaigns.

Loading relevant libraries
#Loading Libraries library(tidyverse) library(lubridate) library(dplyr) library(ggplot2) library(tidyr) library(reshape2)
Reading the cleaned datasets
#Assigning Tables daily_activity <- read.csv("Bellabeat/Cleaned Data/Bellabeat Data - dailyActivity_merged.csv") calories_hourly <- read.csv("Bellabeat/Cleaned Data/Bellabeat Data - hourlyCalories_merged.csv") steps_hourly <- read.csv("Bellabeat/Cleaned Data/Bellabeat Data - hourlySteps_merged.csv") intensities_hourly <- read.csv("Bellabeat/Cleaned Data/Bellabeat Data - hourlyIntensities_merged.csv") METs_by_minute <- read.csv("Bellabeat/Cleaned Data/Bellabeat METs - minuteMETsNarrow_merged.csv") sleep_by_minutes <- read.csv("Bellabeat/Cleaned Data/Bellabeat Sleep Merged - minuteSleep_merged.csv") steps_by_minutes <- read.csv("Bellabeat/Cleaned Data/Bellabeat Steps - minuteStepsNarrow_merged.csv") calories_by_minutes <- read.csv("Bellabeat/Cleaned Data/Bellabeat Calories - minuteCaloriesNarrow_merged.csv") heartrate_by_seconds <- read.csv("Bellabeat/Cleaned Data/Bellabeat Data - heartrate_seconds_merged.csv") intensities_by_minutes <- read.csv("Bellabeat/Cleaned Data/Bellabeat Intensities - minuteIntensitiesNarrow_merged.csv")
Correcting the date time formats for analysis
#Correcting formats for dates daily_activity$ActivityDate = as.POSIXct(daily_activity$ActivityDate, format="%m/%d/%Y", tz=Sys.timezone()) calories_hourly$Date = as.POSIXct(calories_hourly$Date, format="%m/%d/%Y", tz=Sys.timezone()) steps_hourly$Date = as.POSIXct(steps_hourly$Date, format="%m/%d/%Y", tz=Sys.timezone()) calories_hourly$Time = strftime(as.POSIXct(calories_hourly$Time, format="%I:%M:%S %p"),"%I:%M:%S %p") steps_hourly$Time = strftime(as.POSIXct(steps_hourly$Time, format="%I:%M:%S %p"),"%I:%M:%S %p") #Identifying unique Ids n_distinct(daily_activity$Id)

Figuring out brackets of people by steps and calories

I have used four categories in general

  • Less than 5000 steps
  • In between 5000 and 10000 steps
  • In between 10000 and 15000 steps
  • More than 15000 steps

#Summarizing Total Steps by Mean daily_activity_avg <- daily_activity %>% group_by(Id) %>% summarise(Avg_Steps = mean(TotalSteps), Avg_Calories = mean(Calories), Avg_Very_Active_Mins = mean(Very.Active.Minutes),Avg_Fairly_Active_Mins = mean(Fairly.Active.Minutes), Avg_Lightly_Mins = mean(Lightly.Active.Minutes), Avg_Sedentary_Mins = mean(SedentaryMinutes)) # Create a new column called "Step_Category" daily_activity_avg$Step_Category <- cut(daily_activity_avg$Avg_Steps, breaks = c(0, 5000, 10000, 15000, Inf), labels = c("Less than 5000", "5000-10000", "10000-15000", "More than 15000"), include.lowest = TRUE) #Scatter Plot (Avg Steps v/s Unique Ids) ggplot(daily_activity_avg, aes(y = Avg_Steps, x = unique_Id, fill = Avg_Steps, size=Avg_Steps, colour=Step_Category, shape=Step_Category)) + geom_point() + labs(x = "IDs", y = "Average Steps") + theme_minimal()
Scatter Plot (Avg Steps v/s Unique Ids)
Scatter Plot (Avg Steps v/s Unique Ids)
We are able to see that there are three broad categories of people based on their average steps and the general concentration lies within two categories.

Let’s do the same with calories

#Scatter Plot (Avg Calories v/s Unique Ids) ggplot(daily_activity_avg, aes(y = Avg_Calories, x = unique_Id, fill = Avg_Calories, shape=Step_Category, colour=Step_Category)) + geom_point() + labs(x = "IDs", y = "Average Calories") + theme_minimal()
Scatter Plot (Avg Calories v/s Unique Ids)
Scatter Plot (Avg Calories v/s Unique Ids)
We are not able to see a direct correlation here with the categories, so let’s try understanding the relation between Average Steps and Average Calories directly.
#Scatter Plot (Avg Calories v/s Avg Steps) ggplot(daily_activity_avg, aes(y = Avg_Calories, x = Avg_Steps, fill = Avg_Calories, shape=Step_Category, colour=Step_Category)) + geom_point() + labs(x = "Average Steps", y = "Average Calories") + theme_minimal()
Scatter Plot (Avg Calories v/s Avg Steps)
Scatter Plot (Avg Calories v/s Avg Steps)
Here we can see that there is no direct correlation of calories with steps, high calories can be burned even when steps are low on average.

Bifurcating people into 3 catgories

#Pie Chart (Steps Bifurcation) mytable <- table(daily_activity_avg$Step_Category) lbls <- paste(names(mytable), "\n", mytable, sep="") pie(mytable, labels = lbls, main="Pie Chart of Species\n (with sample sizes)")
Pie Chart (Steps Bifurcation)
Pie Chart (Steps Bifurcation)

Understanding activity by weekdays

#Activity by Week Day (metric -> Sum of Steps) daily_activity$WeekDays <- weekdays(daily_activity$ActivityDate) daily_activity_sum <- daily_activity %>% group_by(WeekDays) %>% summarise(total_steps_by_date = sum(TotalSteps), total_calories_by_date = sum(Calories)) #Bar Chart (Weekday v/s Total Calories by Date) ggplot(daily_activity_sum, aes(y = WeekDays, x = total_calories_by_date)) + geom_bar(stat = "identity", position = "dodge", aes(fill= total_calories_by_date)) + labs(x = "Total Calories", y = "Weekday")
Bar Chart (Weekday v/s Total Calories by Date)
Bar Chart (Weekday v/s Total Calories by Date)

Here we can see that:

  • Saturday is the most active day in terms of calories
  • Followed by Friday within a similar range of Saturday
  • Lastly followed by Sunday then Monday


Let’s do the same with steps
#Extracting weekdays from Steps by Hours Data steps_hourly$WeekDays <- weekdays(steps_hourly$Date) #Sum of steps by weekdays steps_hourly_sum <- steps_hourly %>% group_by(WeekDays) %>% summarise(total_steps_by_date = sum(StepTotal)) #Bar Chart (Weekdays v/s Total Step by Date) ggplot(steps_hourly_sum, aes(y = WeekDays, x = total_steps_by_date)) + geom_bar(stat = "identity", position = "dodge", aes(fill= total_steps_by_date)) + labs(x = "Total Steps", y = "Weekday")
Bar Chart (Weekdays v/s Total Step by Date)
Bar Chart (Weekdays v/s Total Step by Date)

Here we can see

  • Saturday is the most active day in terms of steps
  • Followed by Sunday
  • Lastly followed by Monday within a similar range of Sunday

We can concur that Saturdays and Fridays are in general high activity days although Friday also have high average steps but activity on Friday is comparatively low.

Understanding activity in terms of active minutes and hours of the day

#Subset table for activity mins Active_Mins <- subset(daily_activity_avg , select = c(Id, Avg_Sedentary_Mins , Avg_Lightly_Mins, Avg_Fairly_Active_Mins, Avg_Very_Active_Mins)) #Pivoting to longer format Active_Mins_long <- Active_Mins %>% pivot_longer(c(Avg_Sedentary_Mins, Avg_Lightly_Mins, Avg_Fairly_Active_Mins, Avg_Very_Active_Mins), names_to = "variable", values_to = "value") #Activity Mins v/s IDs ggplot(Active_Mins_long, aes(x = Id, y = value, color = variable)) + geom_point() + labs(x = "IDs", y = "Activity Mins") +
Activity Mins v/s IDs
Activity Mins v/s IDs
#Calorie by Hour unique_Id_Calories <- unique(calories_hourly$Id) #Avg Calories by Hour,Id calories_grouped <- calories_hourly %>% group_by(Id,Time) %>% summarise(avg_calories_time = mean(Calories))
#Time conversion for plotting on graph calories_grouped$Time <- factor(calories_grouped$Time, levels = unique(strftime(as.POSIXct(calories_grouped$Time, format="%I:%M:%S %p"),"%I:%M:%S %p"))[order(as.POSIXct(unique(calories_grouped$Time), format="%I:%M:%S %p"))]) #Time v/ Avg Calories ggplot(calories_grouped, aes(y = Time, x = avg_calories_time, color = Time)) + geom_point() + labs(y = "Time", x = "Avg Calories")
Time v/ Avg Calories
After seeing the distribution of activity by hour, we can say that intense activity happens during 5am — 9am (Morning) and 5pm — 8 pm (Evening).

Understanding the intensities of activities

Activities can be light, moderate, or vigorous, according to their MET score

#Summarizing METs by Id METs_avg <- METs_by_minute %>% group_by(Id) %>% summarise(avg_METs = mean(METs)) #Creating categories for METs METs_avg$MET_Category <- cut(METs_avg$avg_METs, breaks = c(0, 10.0, 12.5, 15.0, 17.5, 20, Inf), labels = c("Less than 10.0", "10.0-12.5", "12.5-15.0", "15.0-17.5","17.5-20.0","More than 20.0"), include.lowest = TRUE) #Avg METs v/s Id (w/ MET Category) ggplot(METs_avg, aes(y = avg_METs, x = Id, color = MET_Category, shape = MET_Category, size = MET_Category)) + geom_point() + labs(y = "Avg METs", x = "Id")
Avg METs v/s Id (w/ MET Category)
Avg METs v/s Id (w/ MET Category)
As we have discussed earlier about less correlation between steps and calories, now after seeing a bifurcation in METs we can say, some people are performing high intensity activities as opposed to walking more.

Phase 5 - Share

After understanding this we can create three personas

Persona 1

Persona 1
Persona 1

  • This is a person who generally doesn’t work out and doesn’t walk much.
  • And have an average of 0 to 5000 steps.
  • This person has more sedentary minutes and low METs.

Persona 2

Persona 2
Persona 2

  • This is a person who generally walks decently but doesn’t work out much.
  • The average steps vary for them, the majority of them lie between 5000 to 10000 but very few are between 10000 to 15000.
  • This person has medium METs.

Persona 3

Persona 3
Persona 3

  • This is a person who generally walks and works out decently.
  • The average steps vary for them, the majority of them lie between 5000 to 10000 but very few are between 10000 to 15000.
  • This person has higher METs.

Phase 6- Act

I will be sharing brief ideas for marketing for these personas

Persona 1

Persona 1
Persona 1

  • We need to imprint the idea of working out on this person.
  • We can do that by creating a sense of urgency that everyone is following a healthy lifestyle so should you, where Bellabeat comes into the picture to ease your journey towards fitness (A celebrity would be a bonus to the idea if the budget allows).
  • The other way would be to highlight the importance of a healthy lifestyle through Bellabeat’s existing channels.

Persona 2

Persona 2
Persona 2

  • This person has a disrupted routine and seems to be aware of their lifestyle but is finding it difficult to take action to get on track.
  • This person is looking for something that will help her make her physical activity decisions, so we can focus on depicting a daily routine that works and Bellabeat is helping in enabling it (A celebrity would be a bonus to the idea if the budget allows).

Persona 3

Persona 3
Persona 3

  • This person has a good routine and takes her workouts seriously.
  • This person is looking for a high-level analysis of their workout and lifestyle.

Summary

We can focus on Persona 1 and Persona 2 as they would yield high retention because of their use cases. The first impression should be solid to make that happen.

WIP