Installing and loading required packages

options(repos = c(CRAN = "https://cloud.r-project.org/"))

install.packages("tidyverse") 
## Installing package into 'C:/Users/mayaa/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'tidyverse' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\mayaa\AppData\Local\Temp\RtmpCEZ21p\downloaded_packages
install.packages("lubridate")  
## Installing package into 'C:/Users/mayaa/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'lubridate' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\mayaa\AppData\Local\Temp\RtmpCEZ21p\downloaded_packages
install.packages("ggplot2")  
## Installing package into 'C:/Users/mayaa/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'ggplot2' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\mayaa\AppData\Local\Temp\RtmpCEZ21p\downloaded_packages
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
library(lubridate)
library(ggplot2)
library(readr)
library(dplyr)

Processing Data

In the Processing Phase, I cleaned, transformed, and prepared the data to ensure accuracy and consistency before analysis using R studio as the main tool.

Importing and Combining March–April and April–May Data

# Combine files for heart rate seconds
heartrateSeconds_combined <- rbind(
  read_csv("20160312_20160411/heartrate_seconds_merged.csv"),
  read_csv("20160412_20160512/heartrate_seconds_merged.csv")
)
## Rows: 1154681 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Time
## dbl (2): Id, Value
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2483658 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Time
## dbl (2): Id, Value
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Combine files for minute calories
minuteCalories_combined <- rbind(
  read_csv("20160312_20160411/minuteCaloriesNarrow_merged.csv"),
  read_csv("20160412_20160512/minuteCaloriesNarrow_merged.csv")
)
## Rows: 1445040 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Calories
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1325580 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Calories
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Combine files for minute intensity
minuteIntensity_combined <- rbind(
  read_csv("20160312_20160411/minuteIntensitiesNarrow_merged.csv"),
  read_csv("20160412_20160512/minuteIntensitiesNarrow_merged.csv")
)
## Rows: 1445040 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Intensity
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1325580 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Intensity
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Combine files for minute sleep
minuteSleep_combined <- rbind(
  read_csv("20160312_20160411/minuteSleep_merged.csv"),
  read_csv("20160412_20160512/minuteSleep_merged.csv")
)
## Rows: 198559 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): date
## dbl (3): Id, value, logId
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 188521 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): date
## dbl (3): Id, value, logId
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Combine files for minute steps
minuteSteps_combined <- rbind(
  read_csv("20160312_20160411/minuteStepsNarrow_merged.csv"),
  read_csv("20160412_20160512/minuteStepsNarrow_merged.csv")
)
## Rows: 1445040 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Steps
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1325580 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ActivityMinute
## dbl (2): Id, Steps
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Checking for Duplicates

sum(duplicated(heartrateSeconds_combined))
## [1] 23424
sum(duplicated(minuteSteps_combined))
## [1] 10500
sum(duplicated(minuteCalories_combined))
## [1] 10500
sum(duplicated(minuteIntensity_combined))
## [1] 10500
sum(duplicated(minuteSleep_combined))
## [1] 4300

Remove Duplicates

remove_duplicates <- function(df) {
  df[!duplicated(df), ]
}

heartrateSeconds_combined <- remove_duplicates(heartrateSeconds_combined)
minuteSteps_combined <- remove_duplicates(minuteSteps_combined)
minuteCalories_combined <- remove_duplicates(minuteCalories_combined)
minuteIntensity_combined <- remove_duplicates(minuteIntensity_combined)
minuteSleep_combined <- remove_duplicates(minuteSleep_combined)

Convert Date and Time Fields to Proper Formats

heartrateSeconds_combined$Time <- as.POSIXct(heartrateSeconds_combined$Time, format = "%m/%d/%Y %I:%M:%S %p")
minuteSteps_combined$ActivityMinute <- as.POSIXct(minuteSteps_combined$ActivityMinute, format = "%m/%d/%Y %I:%M:%S %p")
minuteCalories_combined$ActivityMinute <- as.POSIXct(minuteCalories_combined$ActivityMinute, format = "%m/%d/%Y %I:%M:%S %p")
minuteIntensity_combined$ActivityMinute <- as.POSIXct(minuteIntensity_combined$ActivityMinute, format = "%m/%d/%Y %I:%M:%S %p")
minuteSleep_combined$date <- as.POSIXct(minuteSleep_combined$date, format = "%m/%d/%Y %I:%M:%S %p")

Check Structure of Data Frames

str(heartrateSeconds_combined)
## tibble [3,614,915 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Id   : num [1:3614915] 2.02e+09 2.02e+09 2.02e+09 2.02e+09 2.02e+09 ...
##  $ Time : POSIXct[1:3614915], format: "2016-04-01 07:54:00" "2016-04-01 07:54:05" ...
##  $ Value: num [1:3614915] 93 91 96 98 100 101 104 105 102 106 ...
str(minuteSteps_combined)
## tibble [2,760,120 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Id            : num [1:2760120] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
##  $ ActivityMinute: POSIXct[1:2760120], format: "2016-03-12 00:00:00" "2016-03-12 00:01:00" ...
##  $ Steps         : num [1:2760120] 0 0 0 0 0 0 0 0 0 0 ...
str(minuteCalories_combined)
## tibble [2,760,120 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Id            : num [1:2760120] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
##  $ ActivityMinute: POSIXct[1:2760120], format: "2016-03-12 00:00:00" "2016-03-12 00:01:00" ...
##  $ Calories      : num [1:2760120] 0.797 0.797 0.797 0.797 0.797 ...
str(minuteIntensity_combined)
## tibble [2,760,120 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Id            : num [1:2760120] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
##  $ ActivityMinute: POSIXct[1:2760120], format: "2016-03-12 00:00:00" "2016-03-12 00:01:00" ...
##  $ Intensity     : num [1:2760120] 0 0 0 0 0 0 0 0 0 0 ...
str(minuteSleep_combined)
## tibble [382,780 × 4] (S3: tbl_df/tbl/data.frame)
##  $ Id   : num [1:382780] 1.5e+09 1.5e+09 1.5e+09 1.5e+09 1.5e+09 ...
##  $ date : POSIXct[1:382780], format: "2016-03-13 02:39:30" "2016-03-13 02:40:30" ...
##  $ value: num [1:382780] 1 1 1 1 1 1 2 2 1 1 ...
##  $ logId: num [1:382780] 1.11e+10 1.11e+10 1.11e+10 1.11e+10 1.11e+10 ...

Check for Missing Values

sum(is.na(heartrateSeconds_combined))
## [1] 0
sum(is.na(minuteSteps_combined))
## [1] 0
sum(is.na(minuteCalories_combined))
## [1] 0
sum(is.na(minuteIntensity_combined))
## [1] 0
sum(is.na(minuteSleep_combined))
## [1] 0

Analyze Data

Hourly Analysis of Heart Rate, Calories, and Steps

heartrateSeconds_combined$Hour <- format(heartrateSeconds_combined$Time, "%H")
minuteCalories_combined$Hour <- format(minuteCalories_combined$ActivityMinute, "%H")
minuteSteps_combined$Hour <- format(minuteSteps_combined$ActivityMinute, "%H")

avg_heartrate_per_hour <- heartrateSeconds_combined %>%
  group_by(Hour) %>%
  summarize(AverageHeartRate = mean(Value, na.rm = TRUE), 
            MinHeartRate = min(Value, na.rm = TRUE),
            MaxHeartRate = max(Value, na.rm = TRUE))

calories_per_hour <- minuteCalories_combined %>%
  group_by(Hour) %>%
  summarize(AverageCalories = mean(Calories, na.rm = TRUE), 
            MinCalories = min(Calories, na.rm = TRUE),
            MaxCalories = max(Calories, na.rm = TRUE))

steps_per_hour <- minuteSteps_combined %>%
  group_by(Hour) %>%
  summarize(AverageSteps = mean(Steps, na.rm = TRUE), 
            MinSteps = min(Steps, na.rm = TRUE),
            MaxSteps = max(Steps, na.rm = TRUE))

combined_hourly_summary <- avg_heartrate_per_hour %>%
  left_join(calories_per_hour, by = "Hour") %>%
  left_join(steps_per_hour, by = "Hour")

options(max.print = 10000)
print(combined_hourly_summary, n = Inf)
## # A tibble: 24 × 10
##    Hour  AverageHeartRate MinHeartRate MaxHeartRate AverageCalories MinCalories
##    <chr>            <dbl>        <dbl>        <dbl>           <dbl>       <dbl>
##  1 00                67.9           42          177            1.20      0.703 
##  2 01                66.8           40          142            1.17      0.703 
##  3 02                64.5           36          139            1.14      0.703 
##  4 03                62.0           37          121            1.13      0.703 
##  5 04                61.1           39          135            1.13      0.703 
##  6 05                63.5           40          157            1.33      0.703 
##  7 06                73.2           36          169            1.40      0.0485
##  8 07                75.6           38          184            1.54      0.703 
##  9 08                77.7           42          172            1.68      0.703 
## 10 09                80.8           42          189            1.77      0.703 
## 11 10                80.7           43          185            1.80      0.703 
## 12 11                81.2           44          176            1.82      0.703 
## 13 12                83.8           44          179            1.92      0.703 
## 14 13                81.8           38          199            1.86      0.703 
## 15 14                82.3           43          182            1.89      0.703 
## 16 15                81.3           44          181            1.77      0.703 
## 17 16                86.2           45          203            1.86      0.703 
## 18 17                84.7           44          203            1.95      0     
## 19 18                85.6           39          195            1.99      0     
## 20 19                84.4           44          171            1.98      0.703 
## 21 20                80.0           40          182            1.72      0.703 
## 22 21                76.2           40          191            1.57      0.703 
## 23 22                73.2           40          191            1.44      0.562 
## 24 23                70.1           41          142            1.29      0     
## # ℹ 4 more variables: MaxCalories <dbl>, AverageSteps <dbl>, MinSteps <dbl>,
## #   MaxSteps <dbl>

Daily Analysis of Heart Rate, Calories, and Steps

heartrateSeconds_combined$DayOfWeek <- weekdays(heartrateSeconds_combined$Time)
minuteCalories_combined$DayOfWeek <- weekdays(minuteCalories_combined$ActivityMinute)
minuteSteps_combined$DayOfWeek <- weekdays(minuteSteps_combined$ActivityMinute)

avg_heartrate_per_weekday <- heartrateSeconds_combined %>%
  group_by(DayOfWeek) %>%
  summarize(AverageHeartRate = mean(Value, na.rm = TRUE), 
            MinHeartRate = min(Value, na.rm = TRUE),
            MaxHeartRate = max(Value, na.rm = TRUE))

calories_per_weekday <- minuteCalories_combined %>%
  group_by(DayOfWeek) %>%
  summarize(AverageCalories = mean(Calories, na.rm = TRUE), 
            MinCalories = min(Calories, na.rm = TRUE),
            MaxCalories = max(Calories, na.rm = TRUE))

steps_per_weekday <- minuteSteps_combined %>%
  group_by(DayOfWeek) %>%
  summarize(AverageSteps = mean(Steps, na.rm = TRUE), 
            MinSteps = min(Steps, na.rm = TRUE),
            MaxSteps = max(Steps, na.rm = TRUE))

combined_weekly_summary <- avg_heartrate_per_weekday %>%
  left_join(calories_per_weekday, by = "DayOfWeek") %>%
  left_join(steps_per_weekday, by = "DayOfWeek")

options(max.print = 10000)
print(combined_weekly_summary, n = Inf)
## # A tibble: 7 × 10
##   DayOfWeek AverageHeartRate MinHeartRate MaxHeartRate AverageCalories
##   <chr>                <dbl>        <dbl>        <dbl>           <dbl>
## 1 Friday                78.8           37          191            1.60
## 2 Monday                77.4           41          181            1.58
## 3 Saturday              80.1           40          189            1.62
## 4 Sunday                77.6           36          199            1.56
## 5 Thursday              78.1           40          203            1.60
## 6 Tuesday               77.5           40          195            1.61
## 7 Wednesday             77.4           36          181            1.61
## # ℹ 5 more variables: MinCalories <dbl>, MaxCalories <dbl>, AverageSteps <dbl>,
## #   MinSteps <dbl>, MaxSteps <dbl>

Analyzing Activity Intensity Data

minuteIntensity_combined <- minuteIntensity_combined %>%
  mutate(
    Hour = hour(ActivityMinute),
    DayOfWeek = wday(ActivityMinute, label = TRUE, abbr = FALSE)
  )

intensity_summary <- minuteIntensity_combined %>%
  group_by(Intensity) %>%
  summarize(
    Count = n(),  # Total counts for each intensity
    .groups = 'drop'
  ) %>%
  mutate(Intensity = paste0(Intensity, " (", case_when(
    Intensity == 0 ~ "Sedentary",
    Intensity == 1 ~ "Light",
    Intensity == 2 ~ "Moderate",
    Intensity == 3 ~ "Very Active"
  ), ")")) 

most_intensity_by_hour <- minuteIntensity_combined %>%
  group_by(Hour, Intensity) %>%
  summarize(Count = n(), .groups = 'drop') %>%
  group_by(Intensity) %>%
  slice_max(Count, n = 1) %>%
  ungroup() %>% 
  mutate(Intensity = paste0(Intensity, " (", case_when(
    Intensity == 0 ~ "Sedentary",
    Intensity == 1 ~ "Light",
    Intensity == 2 ~ "Moderate",
    Intensity == 3 ~ "Very Active"
  ), ")")) 

most_intensity_by_weekday <- minuteIntensity_combined %>%
  group_by(DayOfWeek, Intensity) %>%
  summarize(Count = n(), .groups = 'drop') %>%
  group_by(Intensity) %>%
  slice_max(Count, n = 1) %>%
  ungroup() %>% 
  mutate(Intensity = paste0(Intensity, " (", case_when(
    Intensity == 0 ~ "Sedentary",
    Intensity == 1 ~ "Light",
    Intensity == 2 ~ "Moderate",
    Intensity == 3 ~ "Very Active"
  ), ")")) 

options(max.print = 10000)
print(intensity_summary, n = Inf)
## # A tibble: 4 × 2
##   Intensity         Count
##   <chr>             <int>
## 1 0 (Sedentary)   2337269
## 2 1 (Light)        359021
## 3 2 (Moderate)      25052
## 4 3 (Very Active)   38778
print(most_intensity_by_hour, n = Inf)
## # A tibble: 4 × 3
##    Hour Intensity        Count
##   <int> <chr>            <int>
## 1     3 0 (Sedentary)   115042
## 2    18 1 (Light)        25170
## 3    19 2 (Moderate)      2437
## 4    19 3 (Very Active)   3486
print(most_intensity_by_weekday, n = Inf)
## # A tibble: 4 × 3
##   DayOfWeek Intensity        Count
##   <ord>     <chr>            <int>
## 1 Tuesday   0 (Sedentary)   342184
## 2 Saturday  1 (Light)        54787
## 3 Saturday  2 (Moderate)      4017
## 4 Tuesday   3 (Very Active)   5889

Analyzing Sleep Patterns

minuteSleep_combined <- minuteSleep_combined %>%
  mutate(
    Hour = hour(date),
    Weekday = wday(date, label = TRUE, abbr = FALSE),
    SleepStateLabel = case_when(
      value == 1 ~ "1 (Asleep)",
      value == 2 ~ "2 (Restless)",
      value == 3 ~ "3 (Awake)"
    )
  )

sleep_summary <- minuteSleep_combined %>%
  group_by(value) %>%
  summarize(
    Count = n(),  
    .groups = 'drop'
  ) %>%
  mutate(value = paste0(value, " (", case_when(
    value == 1 ~ "Asleep",
    value == 2 ~ "Restless",
    value == 3 ~ "Awake"
  ), ")")) 

most_sleep_by_hour <- minuteSleep_combined %>%
  group_by(Hour, SleepStateLabel) %>%
  summarize(Count = n(), .groups = 'drop') %>%
  group_by(SleepStateLabel) %>%
  slice_max(Count, n = 1) %>%
  ungroup()

most_sleep_by_weekday <- minuteSleep_combined %>%
  group_by(Weekday, SleepStateLabel) %>%
  summarize(Count = n(), .groups = 'drop') %>%
  group_by(SleepStateLabel) %>%
  slice_max(Count, n = 1) %>%
  ungroup()

options(max.print = 10000)
print(sleep_summary, n = Inf)
## # A tibble: 3 × 2
##   value         Count
##   <chr>         <int>
## 1 1 (Asleep)   351922
## 2 2 (Restless)  26846
## 3 3 (Awake)      4012
print(most_sleep_by_hour, n = Inf)
## # A tibble: 3 × 3
##    Hour SleepStateLabel Count
##   <int> <chr>           <int>
## 1     3 1 (Asleep)      42715
## 2     6 2 (Restless)     2684
## 3    22 3 (Awake)         437
print(most_sleep_by_weekday, n = Inf)
## # A tibble: 3 × 3
##   Weekday  SleepStateLabel Count
##   <ord>    <chr>           <int>
## 1 Sunday   1 (Asleep)      56648
## 2 Saturday 2 (Restless)     4622
## 3 Sunday   3 (Awake)         804

Combining Data into Comprehensive Datasets

# Create 'combination' folder if it doesn't exist
if (!dir.exists("combination")) {
    dir.create("combination")
  }

# 1. Combo 1: Heart Rate, Steps, and Calories with Hour and Weekday ------------------------
heart_steps_calories_combined <- minuteSteps_combined %>%
  left_join(heartrateSeconds_combined, by = c("Id", "ActivityMinute" = "Time")) %>%
  left_join(minuteCalories_combined, by = c("Id", "ActivityMinute")) %>%
  mutate(
    hour = hour(ActivityMinute),
    weekday = wday(ActivityMinute, label = TRUE)
  )

write.csv(heart_steps_calories_combined, "combination/heart_steps_calories.csv", row.names = FALSE)

# 2. Combo 2: Steps, Intensity, and Calories with Hour and Weekday ------------------------
steps_intensity_calories_combined <- minuteSteps_combined %>%
  left_join(minuteIntensity_combined, by = c("Id", "ActivityMinute")) %>%
  left_join(minuteCalories_combined, by = c("Id", "ActivityMinute")) %>%
  mutate(
    hour = hour(ActivityMinute),              
    weekday = wday(ActivityMinute, label = TRUE)  
  )

write.csv(steps_intensity_calories_combined, "combination/steps_intensity_calories.csv", row.names = FALSE)

# 3. Combo 3: Heart Rate, Intensity, and Sleep with Hour and Weekday ------------------------
heart_intensity_sleep_combined <- heartrateSeconds_combined %>%
  left_join(minuteIntensity_combined, by = c("Id", "Time" = "ActivityMinute")) %>%
  left_join(minuteSleep_combined, by = c("Id", "Time" = "date")) %>%
  mutate(
    hour = hour(Time),                        
    weekday = wday(Time, label = TRUE)  
  )

write.csv(heart_intensity_sleep_combined, "combination/heart_intensity_sleep.csv", row.names = FALSE)


# 4. Combo 4: Calories, Steps, Sleep with Hour and Weekday ------------------------
calories_steps_sleep_combined <- minuteCalories_combined %>%
  left_join(minuteSteps_combined, by = c("Id", "ActivityMinute")) %>%
  left_join(minuteSleep_combined, by = c("Id", "ActivityMinute" = "date")) %>%
  mutate(
    Weekday = wday(ActivityMinute, label = TRUE),  # Extract weekday (abbreviated)
    Hour = hour(ActivityMinute)                    # Extract hour
  )

# Write the combined data to CSV
write.csv(calories_steps_sleep_combined, "combination/calories_steps_sleep_combined.csv", row.names = FALSE)

Visualizations