Loading
Phil Billena

Performance Marketing

Growth Marketing

Data Analytics

Data Visualization

Business Intelligence

Phil Billena

Performance Marketing

Growth Marketing

Data Analytics

Data Visualization

Business Intelligence

Bellabeat Case Study

  • Project: Data Analytics Capstone
  • Categories: Case Study

Introduction

This is my capstone project for the Google Data Analytics Professional Certificate. In this case study, I analyze a public dataset from Kaggle to demonstrate the technical and analytical skills acquired throughout the program. Following the core data analysis framework: Ask, Prepare, Process, Analyze, Share, and Act, I will explore user behaviors to help answer vital business questions for Bellabeat.

About Bellabeat

Founded in 2014 by Urška Sršen and Sandro Mur, Bellabeat is a high-tech wellness company that empowers women with health-focused smart technology. By tracking physical activity, sleep quality, stress levels, and reproductive health, Bellabeat provides women with personalized insights to make informed health decisions.

Bellabeat’s Product Ecosystem

Bellabeat App: The core digital hub tracking activity, sleep, stress, hydration, and reproductive cycles.
Leaf: Bellabeat’s flagship wearable wellness tracker, designed to be worn as a necklace, clip, or bracelet.
Time: A hybrid wellness watch that combines timeless aesthetic design with smart tracking technology.
Spring: A smart water bottle that monitors daily hydration against user activity levels.

Project Focus: In this case study, I analyze smart device usage data from a non-Bellabeat tracker (Fitbit) to discover consumer habits and deliver data-driven marketing recommendations for the Leaf.

Ask

Analyze non-Bella beat smart device usage data to understand consumer behavior and provide strategic recommendations for the Bellabeat marketing team.

Key Stakeholders:

✓ Urška Sršen: Co-founder and Chief Creative Officer of Bellabeat.
Sandro Mur: Mathematician and Co-founder of Bellabeat.
Marketing Analytics Team: The dedicated team responsible for collecting, analyzing, and reporting data to guide marketing strategy.

Prepare

About the Data
This dataset is titled FitBit Fitness Tracking Data and can be found on Kaggle. It is generated by respondents to a survey via Amazon Mechanical Turk over a thirty day span of time, from April 12th, 2016 to May 12th, 2016. The dataset contains the person tracking fitness data of 30 consenting users. Data includes daily steps, daily calories, a sleep log, a weight log, and more. I downloaded the data to be cleaned, analyzed, and visualized on Rstudio.

Credibility of the data
I used the ROCCC method to determine the credibility of the data:

Reliability: I would not consider this data to be reliable. The sample size is only 30, which is at the very bottom of what is considered to be a valid sample size and margin of error. This could potentially limit the amount of analysis that can be done to the data.
Originality: The dataset was originally collected by an Amazon Mechanical Turk, so it is not original.
Comprehensiveness: The dataset is not nearly as comprehensive as it could have been. There is no data on the age, gender, location, etc. This means that there is a possibility that the data could be biased. The users were not asked to wear their FitBits at all times throughout the time frame, so there is data missing within the dataset.
Current: The dataset is from 2016, so it is not current and may not fully represent what fitness tracker data may look like now.
Cited: This data is cited but doesn’t necessarily determine the credibility of the source.There are definitely limitations to this dataset. With that, this data can help provide clues and suggestions, but no concrete answers for the Bellabeat analytics team.

Credibility of the data
First, I installed and loaded the packages necessary to clean and plot the data.

install.packages("tidyverse", repos = "http://cran.us.r-project.org")

##
## The downloaded binary packages are in
## /var/folders/3w/3g5p_cbx277bdmlvy9y8yy440000gn/T//RtmptoIuN3/downloaded_packages

install.packages("dplyr", repos = "http://cran.us.r-project.org")

##
## The downloaded binary packages are in
## /var/folders/3w/3g5p_cbx277bdmlvy9y8yy440000gn/T//RtmptoIuN3/downloaded_packages

install.packages("ggplot2", repos = "http://cran.us.r-project.org")

##
## The downloaded binary packages are in
## /var/folders/3w/3g5p_cbx277bdmlvy9y8yy440000gn/T//RtmptoIuN3/downloaded_packages

install.packages("skimr", repos = "http://cran.us.r-project.org")

##
## The downloaded binary packages are in
## /var/folders/3w/3g5p_cbx277bdmlvy9y8yy440000gn/T//RtmptoIuN3/downloaded_packages

install.packages("janitor", repos = "http://cran.us.r-project.org")

##
## The downloaded binary packages are in
## /var/folders/3w/3g5p_cbx277bdmlvy9y8yy440000gn/T//RtmptoIuN3/downloaded_packages

library(tidyverse)

## ── Attaching packages ──────────────────── tidyverse 1.3.1 ──

## ✓ ggplot2 3.3.5                ✓ purrr 0.3.4
## ✓ tibble 3.1.6                     ✓ dplyr 1.0.8
## ✓ tidyr 1.2.0                       ✓ stringr 1.4.0
## ✓ readr 2.1.2                     ✓ forcats 0.5.1

## ── Conflicts ──────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()

library(dplyr)
library(ggplot2)
library(skimr)
library(janitor)

##
## Attaching package: 'janitor'

## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test

Let’s load and name the data that we will work with. The tables I decided to work with are dailyActivity_merged.csv, weightLogInfo_merged.csv, and sleepDay_merged.csv.

setwd("~/Downloads/Fitabase Data 4.12.16-5.12.16")
daily_activity <- read.csv("dailyActivity_merged.csv")
weight_log <- read.csv("weightLogInfo_merged.csv")
sleep_log <- read.csv("sleepDay_merged.csv")

Now that we’ve got our data loaded, let’s take a closer look at the column names the data sets include.

Process

colnames(daily_activity)

## [1] "Id"                                         "ActivityDate"
## [3] "TotalSteps"                        "TotalDistance"
## [5] "TrackerDistance"             "LoggedActivitiesDistance"
## [7] "VeryActiveDistance"       "ModeratelyActiveDistance"
## [9] "LightActiveDistance"       "SedentaryActiveDistance"
## [11] "VeryActiveMinutes"         "FairlyActiveMinutes"
## [13] "LightlyActiveMinutes"     "SedentaryMinutes"
## [15] "Calories"

colnames(weight_log)

## [1] "Id"       "Date"    "WeightKg"              "WeightPounds"
## [5] "Fat"   "BMI"       "IsManualReport"   "LogId"

colnames(sleep_log)

## [1] "Id" "SleepDay"                "TotalSleepRecords"
## [4] "TotalMinutesAsleep"   "TotalTimeInBed"

The head function gives us the ability to see the first few rows in each dataset.

head(daily_activity)

## Id                             ActivityDate TotalSteps TotalDistance TrackerDistance
## 1 1503960366        4/12/2016                 13162                   8.50                       8.50
## 2 1503960366       4/13/2016                 10735                 6.97                        6.97
## 3 1503960366       4/14/2016                10460                  6.74                        6.74
## 4 1503960366       4/15/2016                  9762                  6.28                        6.28
## 5 1503960366       4/16/2016                 12669                 8.16                          8.16
## 6 1503960366       4/17/2016                  9705                 6.48                          6.48
## LoggedActivitiesDistance      VeryActiveDistance       ModeratelyActiveDistance
## 1                                           0                                     1.88                                     0.55
## 2                                          0                                     1.57                                      0.69
## 3                                          0                                    2.44                                     0.40
## 4                                          0                                     2.14                                      1.26
## 5                                          0                                     2.71                                      0.41
## 6                                          0                                     3.19                                     0.78
## LightActiveDistance          SedentaryActiveDistance     VeryActiveMinutes
## 1                            6.06                                                   0                                        25
## 2                            4.71                                                    0                                        21
## 3                            3.91                                                    0                                       30
## 4                            2.83                                                   0                                       29
## 5                            5.04                                                   0                                       36
## 6                            2.51                                                    0                                       38
##  FairlyActiveMinutes        LightlyActiveMinutes      SedentaryMinutes           Calories
## 1                                13                                       328                                  728                   1985
## 2                               19                                        217                                  776                   1797
## 3                               11                                         181                                   1218                  1776
## 4                             34                                       209                                   726                  1745
## 5                              10                                        221                                   773                   1863
## 6                              20                                      164                                    539                   1728

head(weight_log)

##                     Id                Date                          WeightKg     WeightPounds      Fat         BMI
## 1 1503960366             5/2/2016 11:59:59 PM 52.6               115.9631                   22         22.65
## 2 1503960366            5/3/2016 11:59:59 PM 52.6               115.9631                   NA        22.65
## 3 1927972279             4/13/2016 1:08:52 AM 133.5              294.3171                  NA         47.54
## 4 2873212765             4/21/2016 11:59:59 PM 56.7              125.0021                  NA        21.45
## 5 2873212765             5/12/2016 11:59:59 PM 57.3               126.3249                NA        21.69
## 6 4319703577             4/17/2016 11:59:59 PM 72.4               159.6147                 25        27.45
##        IsManualReport                    LogId
## 1                            True     1.462234e+12
## 2                            True     1.462320e+12
## 3                            False    1.460510e+12
## 4                            True      1.461283e+12
## 5                            True      1.463098e+12
## 6                            True      1.460938e+12

head(sleep_log)

##                     Id                         SleepDay     TotalSleepRecords   TotalMinutesAsleep
## 1 1503960366  4/12/2016 12:00:00 AM                                      1                                  327
## 2 1503960366 4/13/2016 12:00:00 AM                                      2                                 384
## 3 1503960366 4/15/2016 12:00:00 AM                                      1                                  412
## 4 1503960366 4/16/2016 12:00:00 AM                                     2                                  340
## 5 1503960366 4/17/2016 12:00:00 AM                                      1                                  700
## 6 1503960366 4/19/2016 12:00:00 AM                                      1                                 304
## TotalTimeInBed
## 1                    346
## 2                   407
## 3                   442
## 4                   367
## 5                    712
## 6                   320

By using n_distinct function, I can get a count of how many distinct values are in the data sets’ ID columns.

n_distinct(daily_activity$Id)

## [1] 33

n_distinct(weight_log$Id)

## [1] 8

n_distinct(sleep_log$Id)

## [1] 24

From the number of distinct ID’s entered in the three data sets, there were much less people who manually entered their data.Now, to check for duplicates, let’s get a count on the total number of rows in the data sets.

nrow(daily_activity)

## [1] 940

nrow(weight_log)

## [1] 67

nrow(sleep_log)

## [1] 413

To ensure the data is not skewed, let’s check to see if there are any duplicates in our data frames.

nrow(daily_activity[duplicated(daily_activity),])

## [1] 0

nrow(weight_log[duplicated(weight_log),])

## [1] 0

nrow(sleep_log[duplicated(sleep_log),])

## [1] 3

There are three duplicates in our sleep log. I am going to create a new sleep log data frame that only includes unique entries.

sleep_log_new <- unique(sleep_log)

Just to be sure, let’s check our new data frame to look for any duplicates.

nrow(sleep_log_new[duplicated(sleep_log_new),])

## [1] 0

There should now be 410 observations in our sleep log

nrow(sleep_log_new)

## [1] 410

Finally, I would like to check the total number of zero entries their are in the Calories column, this helps me see how many days that users weren’t wearing their device and logging in any data.

Analyze

Now that the data is loaded and clean, let’s look at the datas’ summary statistics.

daily_activity %>%
      select (TotalSteps,
                   TotalDistance,
                   VeryActiveMinutes,
                   FairlyActiveMinutes,
                   LightlyActiveMinutes,
                   SedentaryMinutes,
                   Calories) %>%
summary ()

## TotalSteps     TotalDistance     VeryActiveMinutes    FairlyActiveMinutes
## Min. :       0       Min. : 0.000          Min. : 0.00                    Min. : 0.00
## 1st Qu.: 3790   1st Qu.: 2.620       1st Qu.: 0.00                 1st Qu.: 0.00
## Median : 7406 Median : 5.245  Median : 4.00              Median : 6.00
## Mean : 7638    Mean : 5.490      Mean : 21.16                  Mean : 13.56
## 3rd Qu.:10727   3rd Qu.: 7.713     3rd Qu.: 32.00              3rd Qu.: 19.00
## Max. :36019      Max. :28.030       Max. :210.00                 Max. :143.00
## LightlyActiveMinutes     SedentaryMinutes      Calories
## Min. : 0.                              0 Min. : 0.                       0 Min. : 0
## 1st Qu.:127.0                      1st Qu.: 729.8                 1st Qu.:1828
## Median :199.0                  Median :1057.5             Median :2134
## Mean :192.8                      Mean : 991.2                 Mean :2304
## 3rd Qu.:264.0                   3rd Qu.:1229.5              3rd Qu.:2793
## Max. :518.0                        Max. :1440.0                  Max. :4900

sleep_log_new %>%
        select (TotalSleepRecords,
                      TotalMinutesAsleep,
                      TotalTimeInBed) %>%
summary ()

## TotalSleepRecords     TotalMinutesAsleep        TotalTimeInBed
## Min. :1.00                        Min. : 58.0                          Min. : 61.0
## 1st Qu.:1.00                    1st Qu.:361.0                       1st Qu.:403.8
## Median :1.00                 Median :432.5                   Median :463.0
## Mean :1.12                      Mean :419.2                       Mean :458.5
## 3rd Qu.:1.00                   3rd Qu.:490.0                    3rd Qu.:526.0
## Max. :3.00                      Max. :796.0                        Max. :961.0

weight_log %>%
       select (WeightPounds,
                     BMI) %>%
summary ()

## WeightPounds            BMI
## Min. :116.0                      Min. :21.45
## 1st Qu.:135.4                  1st Qu.:23.96
## Median :137.8               Median :24.39
## Mean :158.8                  Mean :25.19
## 3rd Qu.:187.5                 3rd Qu.:25.56
## Max. :294.3                    Max. :47.54

Observations of the analysis

daily_activity:

  • The average total daily steps taken by users were 7,360
  • On average, users burned 2,304 calories daily
  • Average Very Active Minutes were 21.16 minutes
  • Average Sedentary Minutes were 991.2 minutes
  • On average, people spend a significant amount sitting still and not a lot of time active

sleep_log_new:

weight_log:

  • Rather than focusing on that actual statistical summaries of this data frame, it’s important to note the amount of entries is significantly lower than the other data sets.
  • Users are not entering their weight data into the app.

Share: Visualizations

Let’s plot some of our findings!First, I want to analyze the relationship between total steps and calories.

ggplot(data = daily_activity) +
   geom_point(mapping=aes(x=TotalSteps, y=Calories, color= VeryActiveMinutes)) +
   labs(title = "Relationship Between Total Steps and Calories", x = "Total Steps", y =       "Calories Burned")

Relationship between Total Steps and Calories

correlation between steps taken and calories. The more steps taken, the more calories are burned. Adding the Very Active Minutes as the scale shows the more active minutes a user has, the more calories they burn.

Next, let’s examine the relationship between Total Steps and Sedentary Minutes

ggplot(data = daily_activity) +
   geom_point(mapping = aes(x = TotalSteps, y = SedentaryMinutes,color = Calories)) +
   geom_smooth(mapping=aes(x=TotalSteps, y=SedentaryMinutes)) +
   labs(title = "Relationship Between Total Steps and Sedentary Minutes", x = "Total Steps", y = "Sedentary Minutes")

## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

relationship between total steps and sedentary minutes

steps taken, the more sedentary minutes the user has. Overall, users were not spending a lot of time being active.

Next, let’s compare the relationships between Sedentary Minutes and Calories and Very Active Minutes and Calories.

ggplot(data = daily_activity) +
   geom_point(mapping = aes(x= SedentaryMinutes, y = Calories, color = "red")) +
   geom_smooth(mapping=aes(x=SedentaryMinutes, y=Calories)) +
   labs(title = "Relationship Between Sedentary Minutes and Calories", x = "Sedentary Minutes", y = "Calories Burned")

## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

relationship in sedentary minutes and calories

ggplot(data = daily_activity) +
   geom_point(mapping = aes(x= VeryActiveMinutes, y = Calories, color = "red")) +
   geom_smooth(mapping=aes(x=VeryActiveMinutes, y=Calories)) +
   labs(title = "Relationship Between Very Active Minutes and Calories", x = "Very Active Minutes", y = "Calories Burned")

## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

relationship between very active minutes and calories

between minutes slept and time in bed

ggplot(data = sleep_log_new) +
   geom_point(mapping = aes(x = TotalMinutesAsleep, y = TotalTimeInBed, color = "orange")) +
   geom_smooth(mapping = aes(x = TotalMinutesAsleep, y = TotalTimeInBed)) +
    labs (title = "Relationship Between Total Minutes Asleep and Total Time in Bed", x = "Total Minutes Asleep", y = "Total Time in Bed")

## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Ask: Key Findings

Users are not creating manual entries

  • As stated earlier, there are 33 distinct user id’s in daily activity, but only 24 distinct user ids, and 8 distinct id’s in the weight log.
  • Bellabeat should not focus on gathering data manually
  • If they do, they should promote body positivity, so that users feel comfortable manually entering their weight.

Not all users are sleeping with their fitbit

  • Only 24 users had sleep data. Bellabeat should focus on promoting how comfortable their Leaf fitness device really is, while also promoting the longevity of the battery life.

Users are spending a majority of their time not being active

  • While promoting overall wellness, Bellabeat should promote that you don’t have to do high intensity workouts to burn calories. Just going on a walk burns calories.
  • Bellabeat’s app can include workout ideas at all levels, from yoga to marathon training. Bellabeat should continue to emphasize that all are welcome, and that the Leaf is so much more than tracking fitness.