diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..666c601 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.feather diff --git a/README.md b/README.md new file mode 100644 index 0000000..06e4527 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Apple Health Data Analysis Examples + +This repo contains some example scripts that use Apple Health data to produce +visualizations and reports. + +## Prerequisites + +Use the +[apple-health-exporter](https://github.com/mganjoo/apple-health-exporter) +script to produce a dump of Apple Health data in this directory named +`data.feather`. All scripts rely on the data being present in this directory +**under this exact name**. + +To run the Shiny apps included here, import the `shiny` library. + +```r +library(shiny) +runApp("plotHeartRate.R") +``` + +## Examples + +* `plotHeartRate.R`: Creates an interactive time series plot of heart rate + data. Adapted from [Jeff Johnston](https://github.com/jeffjjohnston)'s + [excellent walkthrough](https://jeffjjohnston.github.io/rstudio/rmarkdown/2016/04/28/explore-your-apple-watch-heart-rate-data.html). diff --git a/loadHealthData.R b/loadHealthData.R new file mode 100644 index 0000000..c092b7a --- /dev/null +++ b/loadHealthData.R @@ -0,0 +1,13 @@ +library(feather) + +dataPath = "data.feather" + +loadHealthData <- function() { + if (!file.exists(dataPath)) { + stop(paste("Cannot find Health data dump under", dataPath, ". Ensure", + "that the file has been created at this path using the", + "exporter.py script.")) + } else { + read_feather(dataPath) + } +} diff --git a/plotHeartRate.R b/plotHeartRate.R new file mode 100644 index 0000000..9a4c324 --- /dev/null +++ b/plotHeartRate.R @@ -0,0 +1,54 @@ +library(dplyr) +library(feather) +library(ggplot2) +library(lubridate) +library(shiny) + +source("loadHealthData.R") + +heartRateData <- loadHealthData() %>% + filter(type == "HKQuantityTypeIdentifierHeartRate") %>% + mutate(dayOnly = as.Date(format(endDate, "%Y-%m-%d"))) + +ui <- fluidPage( + titlePanel("Plot Heart Rate"), + sidebarLayout( + sidebarPanel( + helpText("View heart rate plot across a date range (granularity of 1 day)"), + dateRangeInput("dateRange", label = "Date range", + min = min(heartRateData$dayOnly), + max = max(heartRateData$dayOnly), + start = max(heartRateData$dayOnly), + end = max(heartRateData$dayOnly)) + ), + mainPanel( + plotOutput("heartRate"), + tableOutput("dataSummary") + ) + ) +) + +server <- function(input, output) { + heartRateDataForRange <- reactive({ + begin <- as.Date(input$dateRange[1]) + end <- as.Date(input$dateRange[2]) + days(1) + heartRateData %>% filter(begin <= endDate & endDate < end) + }) + output$heartRate <- renderPlot({ + heartRateDataForRange() %>% + ggplot(aes(x = endDate, y = value)) + geom_line() + + labs(x = "Date", y = "Heart rate (bpm)") + }) + output$dataSummary <- renderTable({ + heartRateDataForRange() %>% + summarize( + earliestRecord = as.character(min(endDate)), + latestRecord = as.character(max(endDate)), + maxHeartRate = max(value), + minHeartRate = min(value), + numMeasurements = n() + ) + }) +} + +shinyApp(ui = ui, server = server)