This project has been initiated by the CEO and Co-Founder of the company Bellabeat, she wants to know how can the trends in smart devices inform Bellabeat marketing strategy. I was assigned to this project, being a junior data analyst who joined the company six months ago. It is going to be a great opportunity for me to apply my knowledge in the data analytics field to come up with useful insights and conclusions. The marketing department are going to make strategic decisions based on the insights gained from this analysis in terms of customers’ behaviors.
My main stakeholders are: - The CEO and Co-Founder Sršen. - The CO of the marketing department. ### Business Task: Discover trends in how people are using smart devices and make recommandations on for how these trends can inform Bellabeat marketing strategy. # Data Collection
The dataset that we will be using in this analysis is an open source dataset taken from the well known platform KAGGLE, it gives a detailed recording of different daily activities of a certain num # Data Processing Documentation of any cleaning or manipulation of data ## Set up the R environment
install.packages("tidyverse")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
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.5.1 ✔ 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
We have decided to use R programming language for this project because the dataset is too large for a spearsheet, the R give us the possibility to clean,transform and analyse data but also and more importantly allows great ways of visualization. Before we can upload our data, let’s first check the default path to our directory using the following function:
getwd()
## [1] "/cloud/project"
Now, we can uppload our files using thefunction read.csv, included in the package READR that has been installed with TIDYVERSE. Additionaly, I used to the function na.omit to erase null values from the rows in the different data frame. Later on, I am going to show you how does each data frame look like using different functions.
heartrate_seconds <- na.omit(read.csv("heartrate_seconds_merged.csv"))
#Hourly recordings
hourly_calories<- na.omit(read.csv("hourlyCalories_merged.csv"))
hourly_intensities <- na.omit(read.csv("hourlyIntensities_merged.csv"))
hourly_steps <- na.omit(read.csv("hourlySteps_merged.csv"))
#minute recordings
minute_calories <- na.omit(read.csv("minuteCaloriesNarrow_merged.csv"))
minute_intensities <- na.omit(read.csv("minuteIntensitiesNarrow_merged.csv"))
minute_mets_narrow <- na.omit(read.csv("minuteMETsNarrow_merged.csv"))
minute_sleep <- na.omit(read.csv("minuteSleep_merged.csv"))
minute_steps_narrow <- na.omit(read.csv("minuteStepsNarrow_merged.csv"))
#Weight Log Info
weight_log_inf<- na.omit(read.csv("weightLogInfo_merged.csv"))
let’s as explore a little bit our dataset by showing first rows, let’s look at the columns names, number of rows,type of data and other useful informations. We will be using two functions head and gimpse, of course there are many others but let us use only these two for the moment :
head(heartrate_seconds)
## Id Time Value
## 1 2022484408 4/1/2016 7:54:00 AM 93
## 2 2022484408 4/1/2016 7:54:05 AM 91
## 3 2022484408 4/1/2016 7:54:10 AM 96
## 4 2022484408 4/1/2016 7:54:15 AM 98
## 5 2022484408 4/1/2016 7:54:20 AM 100
## 6 2022484408 4/1/2016 7:54:25 AM 101
head(hourly_calories)
## Id ActivityHour Calories
## 1 1503960366 3/12/2016 12:00:00 AM 48
## 2 1503960366 3/12/2016 1:00:00 AM 48
## 3 1503960366 3/12/2016 2:00:00 AM 48
## 4 1503960366 3/12/2016 3:00:00 AM 48
## 5 1503960366 3/12/2016 4:00:00 AM 48
## 6 1503960366 3/12/2016 5:00:00 AM 48
head(hourly_intensities)
## Id ActivityHour TotalIntensity AverageIntensity
## 1 1503960366 3/12/2016 12:00:00 AM 0 0
## 2 1503960366 3/12/2016 1:00:00 AM 0 0
## 3 1503960366 3/12/2016 2:00:00 AM 0 0
## 4 1503960366 3/12/2016 3:00:00 AM 0 0
## 5 1503960366 3/12/2016 4:00:00 AM 0 0
## 6 1503960366 3/12/2016 5:00:00 AM 0 0
head(hourly_steps)
## Id ActivityHour StepTotal
## 1 1503960366 3/12/2016 12:00:00 AM 0
## 2 1503960366 3/12/2016 1:00:00 AM 0
## 3 1503960366 3/12/2016 2:00:00 AM 0
## 4 1503960366 3/12/2016 3:00:00 AM 0
## 5 1503960366 3/12/2016 4:00:00 AM 0
## 6 1503960366 3/12/2016 5:00:00 AM 0
head(minute_calories)
## Id ActivityMinute Calories
## 1 1503960366 3/12/2016 12:00:00 AM 0.7973
## 2 1503960366 3/12/2016 12:01:00 AM 0.7973
## 3 1503960366 3/12/2016 12:02:00 AM 0.7973
## 4 1503960366 3/12/2016 12:03:00 AM 0.7973
## 5 1503960366 3/12/2016 12:04:00 AM 0.7973
## 6 1503960366 3/12/2016 12:05:00 AM 0.7973
head(minute_intensities)
## Id ActivityMinute Intensity
## 1 1503960366 3/12/2016 12:00:00 AM 0
## 2 1503960366 3/12/2016 12:01:00 AM 0
## 3 1503960366 3/12/2016 12:02:00 AM 0
## 4 1503960366 3/12/2016 12:03:00 AM 0
## 5 1503960366 3/12/2016 12:04:00 AM 0
## 6 1503960366 3/12/2016 12:05:00 AM 0
head(minute_mets_narrow)
## Id ActivityMinute METs
## 1 1503960366 3/12/2016 12:00:00 AM 10
## 2 1503960366 3/12/2016 12:01:00 AM 10
## 3 1503960366 3/12/2016 12:02:00 AM 10
## 4 1503960366 3/12/2016 12:03:00 AM 10
## 5 1503960366 3/12/2016 12:04:00 AM 10
## 6 1503960366 3/12/2016 12:05:00 AM 10
head(minute_sleep)
## Id date value logId
## 1 1503960366 3/13/2016 2:39:30 AM 1 11114919637
## 2 1503960366 3/13/2016 2:40:30 AM 1 11114919637
## 3 1503960366 3/13/2016 2:41:30 AM 1 11114919637
## 4 1503960366 3/13/2016 2:42:30 AM 1 11114919637
## 5 1503960366 3/13/2016 2:43:30 AM 1 11114919637
## 6 1503960366 3/13/2016 2:44:30 AM 1 11114919637
head(minute_steps_narrow)
## Id ActivityMinute Steps
## 1 1503960366 3/12/2016 12:00:00 AM 0
## 2 1503960366 3/12/2016 12:01:00 AM 0
## 3 1503960366 3/12/2016 12:02:00 AM 0
## 4 1503960366 3/12/2016 12:03:00 AM 0
## 5 1503960366 3/12/2016 12:04:00 AM 0
## 6 1503960366 3/12/2016 12:05:00 AM 0
head(weight_log_inf)
## Id Date WeightKg WeightPounds Fat BMI
## 1 1503960366 4/5/2016 11:59:59 PM 53.3 117.5064 22 22.97
## 3 2347167796 4/3/2016 11:59:59 PM 63.4 139.7731 10 24.77
## IsManualReport LogId
## 1 True 1.459901e+12
## 3 True 1.459728e+12
glimpse(heartrate_seconds)
## Rows: 1,154,681
## Columns: 3
## $ Id <dbl> 2022484408, 2022484408, 2022484408, 2022484408, 2022484408, 2022…
## $ Time <chr> "4/1/2016 7:54:00 AM", "4/1/2016 7:54:05 AM", "4/1/2016 7:54:10 …
## $ Value <int> 93, 91, 96, 98, 100, 101, 104, 105, 102, 106, 109, 112, 111, 109…
glimpse(hourly_calories)
## Rows: 24,084
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 150396036…
## $ ActivityHour <chr> "3/12/2016 12:00:00 AM", "3/12/2016 1:00:00 AM", "3/12/20…
## $ Calories <int> 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 89, 134, 130, 81,…
glimpse(hourly_intensities)
## Rows: 24,084
## Columns: 4
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 15039…
## $ ActivityHour <chr> "3/12/2016 12:00:00 AM", "3/12/2016 1:00:00 AM", "3/1…
## $ TotalIntensity <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 49, 47, 20, 121, 12…
## $ AverageIntensity <dbl> 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.0…
glimpse(hourly_steps)
## Rows: 24,084
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 150396036…
## $ ActivityHour <chr> "3/12/2016 12:00:00 AM", "3/12/2016 1:00:00 AM", "3/12/20…
## $ StepTotal <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 551, 1764, 1259, 253, 4470,…
glimpse(minute_calories)
## Rows: 1,445,040
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960…
## $ ActivityMinute <chr> "3/12/2016 12:00:00 AM", "3/12/2016 12:01:00 AM", "3/12…
## $ Calories <dbl> 0.7973, 0.7973, 0.7973, 0.7973, 0.7973, 0.7973, 0.7973,…
glimpse(minute_intensities)
## Rows: 1,445,040
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960…
## $ ActivityMinute <chr> "3/12/2016 12:00:00 AM", "3/12/2016 12:01:00 AM", "3/12…
## $ Intensity <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
glimpse(minute_mets_narrow)
## Rows: 1,445,040
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960…
## $ ActivityMinute <chr> "3/12/2016 12:00:00 AM", "3/12/2016 12:01:00 AM", "3/12…
## $ METs <int> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,…
glimpse(minute_sleep)
## Rows: 198,559
## Columns: 4
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960366, 1503…
## $ date <chr> "3/13/2016 2:39:30 AM", "3/13/2016 2:40:30 AM", "3/13/2016 2:41:…
## $ value <int> 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ logId <dbl> 11114919637, 11114919637, 11114919637, 11114919637, 11114919637,…
glimpse(minute_steps_narrow)
## Rows: 1,445,040
## Columns: 3
## $ Id <dbl> 1503960366, 1503960366, 1503960366, 1503960366, 1503960…
## $ ActivityMinute <chr> "3/12/2016 12:00:00 AM", "3/12/2016 12:01:00 AM", "3/12…
## $ Steps <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
glimpse(weight_log_inf)
## Rows: 2
## Columns: 8
## $ Id <dbl> 1503960366, 2347167796
## $ Date <chr> "4/5/2016 11:59:59 PM", "4/3/2016 11:59:59 PM"
## $ WeightKg <dbl> 53.3, 63.4
## $ WeightPounds <dbl> 117.5064, 139.7731
## $ Fat <int> 22, 10
## $ BMI <dbl> 22.97, 24.77
## $ IsManualReport <chr> "True", "True"
## $ LogId <dbl> 1.459901e+12, 1.459728e+12
We will now merge the hourly records using the function merge
#First, we will install and load the package *janitor*
install.packages("janitor")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
library(janitor)
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
#Second, let's call the new data set hourly_record, the primary key is "Id":
hourly_record<- merge(hourly_calories,hourly_steps,by=c("Id","ActivityHour"))
head(hourly_record)
## Id ActivityHour Calories StepTotal
## 1 1503960366 3/12/2016 1:00:00 AM 48 0
## 2 1503960366 3/12/2016 1:00:00 PM 81 253
## 3 1503960366 3/12/2016 10:00:00 AM 89 551
## 4 1503960366 3/12/2016 10:00:00 PM 123 1132
## 5 1503960366 3/12/2016 11:00:00 AM 134 1764
## 6 1503960366 3/12/2016 11:00:00 PM 111 918
We will now add the information about intensities to the merged table that we just created:
install.packages("janitor")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
library(janitor)
hourly_record<- merge(hourly_record,hourly_intensities,by=c("Id","ActivityHour"))
head(hourly_record)
## Id ActivityHour Calories StepTotal TotalIntensity
## 1 1503960366 3/12/2016 1:00:00 AM 48 0 0
## 2 1503960366 3/12/2016 1:00:00 PM 81 253 20
## 3 1503960366 3/12/2016 10:00:00 AM 89 551 26
## 4 1503960366 3/12/2016 10:00:00 PM 123 1132 41
## 5 1503960366 3/12/2016 11:00:00 AM 134 1764 49
## 6 1503960366 3/12/2016 11:00:00 PM 111 918 35
## AverageIntensity
## 1 0.000000
## 2 0.333333
## 3 0.433333
## 4 0.683333
## 5 0.816667
## 6 0.583333
To be able to add the information about minute_sleep to this merged table, we need to summarise it, let’s do it using this code and the result is going to be named daily_minute_sleep :
daily_minute_sleep<-minute_sleep %>%
group_by(Id) %>%
summarise("sum_sleep_minute"=sum(value))
head(daily_minute_sleep)
## # A tibble: 6 × 2
## Id sum_sleep_minute
## <dbl> <int>
## 1 1503960366 10459
## 2 1644430081 2520
## 3 1844505072 2546
## 4 1927972279 12102
## 5 2022484408 153
## 6 2026352035 18848
We will merge the obtained table with the hourly_record created previously. The result is going to be our daily_records_sum
Daily_records_sum<- merge(daily_minute_sleep,
hourly_record %>%
group_by(Id) %>%
summarise(daily_avg_calories=round(mean(Calories),digits=2),
daily_avg_steps=round(mean(StepTotal),digits=2),
daily_avg_intensities=round(mean(TotalIntensity),digits=2)),
by="Id")
head(Daily_records_sum)
## Id sum_sleep_minute daily_avg_calories daily_avg_steps
## 1 1503960366 10459 81.08 547.71
## 2 1644430081 2520 126.72 334.79
## 3 1844505072 2546 62.71 69.61
## 4 1927972279 12102 109.39 227.33
## 5 2022484408 153 108.86 530.94
## 6 2026352035 18848 61.66 187.95
## daily_avg_intensities
## 1 17.24
## 2 14.83
## 3 3.11
## 4 9.02
## 5 18.52
## 6 8.84
Same thing with heart rate values, let’s summarize it using the average per day, the result is going to be named daily_minute_sleep :
daily_heartrate_avg<- heartrate_seconds %>%
group_by(Id) %>%
summarise(avg_heartrate=mean(Value))
head(daily_heartrate_avg)
## # A tibble: 6 × 2
## Id avg_heartrate
## <dbl> <dbl>
## 1 2022484408 81.7
## 2 2026352035 65.8
## 3 2347167796 76.1
## 4 4020332650 81.9
## 5 4558609924 79.6
## 6 5553957443 69.4
Finally, we will merge the obtained table(daily_heartrate_avg) with the daily_records_sum created previously. The result is going to be our daily_records that give us all information that we need for our analysis, we will show the result using the function “head”.
Daily_records<- merge(daily_heartrate_avg, Daily_records_sum,by="Id")
#To show you how does the result look like, we will use the function head():
head(Daily_records)
## Id avg_heartrate sum_sleep_minute daily_avg_calories daily_avg_steps
## 1 2022484408 81.68851 153 108.86 530.94
## 2 2026352035 65.77904 18848 61.66 187.95
## 3 2347167796 76.06874 14940 89.20 434.17
## 4 4020332650 81.90180 6101 112.52 155.81
## 5 4558609924 79.55230 666 74.88 191.29
## 6 5553957443 69.41880 16231 75.23 290.44
## daily_avg_intensities
## 1 18.52
## 2 8.84
## 3 14.97
## 4 6.74
## 5 9.03
## 6 10.33
The data is cleaned up since we used the function na.omit() at the beggining when we upploaded our data, the columns that we will be used are created and renamed as needed, like for example daily_avgcalories… # Data Analysis and Data Sharing We have discovered an important correlation between a healthy sleep and the physical exercice, people who make average steps per day are likely to sleep well. We found the same trend between sleep and intensity of exercising. People are most likely to use devices that measure at the same time their physical activities,their heart rate and their sleep quality. Take a look on the following graph, but first we will make sure that we have the needed package which is ggplot2. let’s run the code library(ggplot2):
install.packages("ggplot2")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
library(ggplot2)
##Scatter Plot:
ggplot(Daily_records, aes(x=sum_sleep_minute))+
geom_point(mapping=aes(y=daily_avg_steps,shape="daily_avg_steps",color="daily_avg_steps"))+
geom_point(mapping=aes(y=daily_avg_intensities,shape="daily_avg_intensities",color="daily_avg_intensities"))+
geom_point(mapping=aes(y=daily_avg_calories,shape="daily_avg_calories",color="daily_avg_calories"))+
geom_point(mapping=aes(y=avg_heartrate, color="avg_heartrate",shape="avg_heartrate"))+
labs(title="variation",x="Sleep",y="Physical Exercice")+
theme_minimal()
The strategic orientation of the company should be 360 degree, do not focus on one single segment like devices designed to monitoring heart rate for example but focus on all aspects of people’s life, consider offering a one smart solution that can answer all questions about each aspect of customer’s life.