class: left, bottom, title-slide .title[ # Data Prescription ] .subtitle[ ## Introducing R for Nursing Analytics ] .author[ ### Dr. Bret Staudt Willet ] .date[ ### December 18, 2024 ] --- class: inverse, center, middle #
**View the slides:** [bretsw.com/nursing24-workshop](https://bretsw.com/nursing24-workshop) --- class: inverse, center, middle #
<br><br> **Part 1:** <br> Introduction to R --- #
Our Constructivist Approach -- 1. I'll introduce some concepts -- 1. You'll try some code -- 1. We'll all discuss together -- <img src="img/tech_support_cheat_sheet.png" width="320px" style="display: block; margin: auto;" /> <div class="caption"> <p><a href="https://xkcd.com/627/" target="_blank">'Tech Support Cheat Sheet' from XKCD</a></p> </div> --- class: inverse, center, middle #
<br><br> Background <br> on R and RStudio --- #
Why Learn R? -- - It is increasingly used in academia -- - It is cross-platform, open-source, and freely-available -- - It is a programming language and quite flexible -- - It is capable of carrying out basic and complex statistical analyses -- - It is able to work with data small (*n* = 10) and large (*n* = 1,000,000+) efficiently -- - There is a great, inclusive community of users and developers --- #
Setting up R ### To download R - Visit [**cran.r-project.org**](https://cran.r-project.org/) to download R - Find your operating system (Mac, Windows, or Linux) - Download the 'latest release' on the page for your operating system and download and install the application -- ### To download RStudio Desktop - Visit [**posit.co**](https://posit.co/download/rstudio-desktop/) to download RStudio Desktop from the parent company, Posit - Find your operating system (Mac, Windows, or Linux) - Download the 'latest release' on the page for your operating system and download and install the application -- ### RMarkdown - RMarkdown is a data analysis "notebook" that combines text with code and output - It is a great file type to use when beginning to use R and to create reproducible analyses - It is fun to use because you can generate different types of output (Word, PDF, and even web-based) --- class: inverse, center, middle #
Try it Out! --- #
Try it Out! What do you think this code will do? ``` r starwars ``` --- #
Try it Out! Let's see! ``` r starwars ``` ``` ## # A tibble: 87 × 14 ## name height mass hair_color skin_color eye_color birth_year sex gender ## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> ## 1 Luke Sk… 172 77 blond fair blue 19 male mascu… ## 2 C-3PO 167 75 <NA> gold yellow 112 none mascu… ## 3 R2-D2 96 32 <NA> white, bl… red 33 none mascu… ## 4 Darth V… 202 136 none white yellow 41.9 male mascu… ## 5 Leia Or… 150 49 brown light brown 19 fema… femin… ## 6 Owen La… 178 120 brown, gr… light blue 52 male mascu… ## 7 Beru Wh… 165 75 brown light blue 47 fema… femin… ## 8 R5-D4 97 32 <NA> white, red red NA none mascu… ## 9 Biggs D… 183 84 black light brown 24 male mascu… ## 10 Obi-Wan… 182 77 auburn, w… fair blue-gray 57 male mascu… ## # ℹ 77 more rows ## # ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>, ## # vehicles <list>, starships <list> ``` --- #
Try it Out! What do you think this code will do? ``` r glimpse(starwars) ``` --- #
Try it Out! Let's see! ``` r glimpse(starwars) ``` ``` ## Rows: 87 ## Columns: 14 ## $ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Or… ## $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 2… ## $ mass <dbl> 77.0, 75.0, 32.0, 136.0, 49.0, 120.0, 75.0, 32.0, 84.0, 77.… ## $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "brown", N… ## $ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "light", "… ## $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "blue",… ## $ birth_year <dbl> 19.0, 112.0, 33.0, 41.9, 19.0, 52.0, 47.0, NA, 24.0, 57.0, … ## $ sex <chr> "male", "none", "none", "male", "female", "male", "female",… ## $ gender <chr> "masculine", "masculine", "masculine", "masculine", "femini… ## $ homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "T… ## $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human", "Huma… ## $ films <list> <"A New Hope", "The Empire Strikes Back", "Return of the J… ## $ vehicles <list> <"Snowspeeder", "Imperial Speeder Bike">, <>, <>, <>, "Imp… ## $ starships <list> <"X-wing", "Imperial shuttle">, <>, <>, "TIE Advanced x1",… ``` --- #
Try it Out! What do you think this code will do? ``` r starwars %>% filter(height <= 150) %>% arrange(height) %>% select(name, sex, height, mass, homeworld) ``` --- #
Try it Out! Let's see! ``` r starwars %>% filter(height <= 120) %>% arrange(height) %>% select(name, sex, height, mass, homeworld) ``` ``` ## # A tibble: 8 × 5 ## name sex height mass homeworld ## <chr> <chr> <int> <dbl> <chr> ## 1 Yoda male 66 17 <NA> ## 2 Ratts Tyerel male 79 15 Aleen Minor ## 3 Wicket Systri Warrick male 88 20 Endor ## 4 Dud Bolt male 94 45 Vulpter ## 5 R2-D2 none 96 32 Naboo ## 6 R4-P17 none 96 NA <NA> ## 7 R5-D4 none 97 32 Tatooine ## 8 Sebulba male 112 40 Malastare ``` --- #
Try it Out! What do you think this code will do? ``` r starwars %>% unnest(starships) %>% select(name, gender, starships) %>% head(15) ``` --- #
Try it Out! Let's see! ``` r starwars %>% unnest(starships) %>% select(starships, name, gender) %>% head(15) ``` ``` ## # A tibble: 15 × 3 ## starships name gender ## <chr> <chr> <chr> ## 1 X-wing Luke Skywalker masculine ## 2 Imperial shuttle Luke Skywalker masculine ## 3 TIE Advanced x1 Darth Vader masculine ## 4 X-wing Biggs Darklighter masculine ## 5 Jedi starfighter Obi-Wan Kenobi masculine ## 6 Trade Federation cruiser Obi-Wan Kenobi masculine ## 7 Naboo star skiff Obi-Wan Kenobi masculine ## 8 Jedi Interceptor Obi-Wan Kenobi masculine ## 9 Belbullab-22 starfighter Obi-Wan Kenobi masculine ## 10 Naboo fighter Anakin Skywalker masculine ## 11 Trade Federation cruiser Anakin Skywalker masculine ## 12 Jedi Interceptor Anakin Skywalker masculine ## 13 Millennium Falcon Chewbacca masculine ## 14 Imperial shuttle Chewbacca masculine ## 15 Millennium Falcon Han Solo masculine ``` --- #
Try it Out! What do you think this code will do? ``` r starwars %>% unnest(starships) %>% mutate(vehicles = strsplit(starships, ",")) %>% unnest(starships) %>% select(name, gender, starships) %>% group_by(gender) %>% count() ``` --- #
Try it Out! Let's see! ``` r starwars %>% unnest(starships) %>% mutate(vehicles = strsplit(starships, ",")) %>% unnest(starships) %>% select(name, gender, starships) %>% group_by(gender) %>% count() %>% arrange(desc(n)) ``` ``` ## # A tibble: 3 × 2 ## # Groups: gender [3] ## gender n ## <chr> <int> ## 1 masculine 26 ## 2 feminine 3 ## 3 <NA> 2 ``` --- #
Visualizing Data ``` r starwars %>% ggplot() + geom_point(aes(x = mass, y = height, color = gender)) ``` <img src="index_files/figure-html/unnamed-chunk-12-1.png" style="display: block; margin: auto;" /> --- class: inverse, center, middle #
<br><br> **Part 2:** <br> Fitbit Data --- class: inverse, center, middle #
<br><br> Set up the <br> Fitbit API ### Step 1: Register a Fitbit developer app This example of health analytics utilizes the {fitbitr} R package ([Kaye, 2021](https://matthewrkaye.com/fitbitr/)). The functions in the package are relatively straightforward, but getting access to the [Fitbit API](https://dev.fitbit.com/build/reference/web-api/) set up is a bit tricky. --- class: inverse, center, middle #
<br><br> Set up the <br> Fitbit API ### Step 1: Register a Fitbit developer app The first thing to do is register a new Fitbit developer app at [dev.fitbit.com](https://dev.fitbit.com/apps/new). --- #
Set up the Fitbit API ### Step 1: Register a Fitbit developer app Here's how I completed the form: <hr> - **Application Name:** `r-health-tracker` - **Description:** `fitbitr script` - **Application Website URL:** `https://github.com/bretsw/fitbit` (replace with your GitHub repo) - **Organization:** `bretsw` (replace with your GitHub user name) - **Organization Website URL:** `https://github.com/bretsw/fitbit` (replace with your GitHub repo) - **Terms of Service URL:** `https://github.com/bretsw/fitbit` (replace with your GitHub repo) - **Privacy Policy URL:** `https://github.com/bretsw/fitbit` (replace with your GitHub repo) - **OAuth 2.0 Application Type:** `Personal` - **Redirct URL:** `http://localhost:1410/` - **Default Access Type:** `Read Only` --- #
Set up the Fitbit API ### Step 1: Register a Fitbit developer app I got a warning from the dev website that the redirect URL needs to be an `https`, but it needs to be in the exact format I have above, because this is how R is set up to take you back to your R console. If you have to, complete the initial form with `https://localhost:1410/` initially, then go back and edit it before you run your R script. Once you submit your Fitbit dev app, you will be taken to a webpage that lists your **OAuth 2.0 Client ID** and **Client Secret**. --- class: inverse, center, middle #
<br><br> Set up the <br> Fitbit API ### Step 2: Record your dev app credentials --- #
Set up the Fitbit API ### Step 2: Record your dev app credentials Be sure to make a copy of your Fitbit dev app **OAuth 2.0 Client ID** and **Client Secret**. I find it easiest to securely store these in my local R user environment. You can open this file with the command `usethis::edit_r_environ()` and then retrieve stored variables with `Sys.getenv()`. In my R script below, note that you should save your credentials in the form `FITBIT_CLIENT_ID = XXXXXX` and `FITBIT_CLIENT_SECRET = XXXXXX`. Once you have your credentials stored, close the .Renviron file and quit out of R entirely. When you restart R, your credentials are ready to go. You can check if things are stored correctly by running: `Sys.getenv('FITBIT_CLIENT_ID')` and `Sys.getenv('FITBIT_CLIENT_SECRET')`. Just be sure that you don't share these credentials with anyone! --- class: inverse, center, middle #
<br><br> Set up the <br> Fitbit API ### Step 3: Retrieve your Fitbit data --- #
Set up the Fitbit API ### Step 3: Retrieve your Fitbit data ``` r fitbitr::generate_fitbitr_token( app_name = Sys.getenv('FITBIT_APP_NAME'), client_id = Sys.getenv('FITBIT_CLIENT_ID'), client_secret = Sys.getenv('FITBIT_CLIENT_SECRET'), callback = Sys.getenv('FITBIT_REDIRECT_URL'), cache = FALSE ) ``` --- class: inverse, center, middle #
<br><br> Try it Out! --- #
Try it Out! What do you think this code will do? ``` r start_date <- lubridate::mdy("12/01/2024") - lubridate::days(1094) end_date <- lubridate::mdy("12/01/2024") steps_df <- get_steps(start_date, end_date) ``` --- #
Try it Out! ### Look at your daily steps ``` r tail(steps_df, 15) ``` ``` ## # A tibble: 15 × 2 ## date steps ## <date> <dbl> ## 1 2024-11-17 12815 ## 2 2024-11-18 4123 ## 3 2024-11-19 8120 ## 4 2024-11-20 7895 ## 5 2024-11-21 9340 ## 6 2024-11-22 5913 ## 7 2024-11-23 3793 ## 8 2024-11-24 5958 ## 9 2024-11-25 8504 ## 10 2024-11-26 5596 ## 11 2024-11-27 5505 ## 12 2024-11-28 4927 ## 13 2024-11-29 10361 ## 14 2024-11-30 6436 ## 15 2024-12-01 8648 ``` --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point() ``` <img src="index_files/figure-html/unnamed-chunk-18-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point() + geom_smooth() ``` <img src="index_files/figure-html/unnamed-chunk-19-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point() + geom_smooth() + xlab(NULL) + ylab("Steps per Day") ``` <img src="index_files/figure-html/unnamed-chunk-20-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point() + geom_smooth() + xlab(NULL) + ylab("Steps per Day") + ggtitle("Number of Daily Steps") ``` <img src="index_files/figure-html/unnamed-chunk-21-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point() + geom_smooth() + xlab(NULL) + ylab("Steps per Day") + ggtitle("Number of Daily Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-22-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point(color = "blue", alpha = 0.5) + geom_smooth(color = "green") + xlab(NULL) + ylab("Steps per Day") + ggtitle("Number of Daily Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-23-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r steps_df %>% ggplot(aes(x = date, y = steps)) + geom_point(color = "blue", alpha = 0.5) + geom_smooth(color = "green") + xlab(NULL) + scale_y_continuous(labels = scales::comma) + ylab("Steps per Day") + ggtitle("Number of Daily Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-24-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Try it Out! What do you think this code will do? ``` r hr <- get_heart_rate_intraday(lubridate::mdy("11/28/2024")) ``` --- #
Try it Out! Let's see! ``` r head(hr, 15) ``` ``` ## # A tibble: 15 × 2 ## time heart_rate ## <dttm> <dbl> ## 1 2024-11-28 08:59:56 70 ## 2 2024-11-28 09:00:06 72 ## 3 2024-11-28 09:00:11 82 ## 4 2024-11-28 09:00:16 78 ## 5 2024-11-28 09:00:26 79 ## 6 2024-11-28 09:00:36 82 ## 7 2024-11-28 09:00:41 83 ## 8 2024-11-28 09:00:46 83 ## 9 2024-11-28 09:01:01 89 ## 10 2024-11-28 09:01:06 91 ## 11 2024-11-28 09:01:11 88 ## 12 2024-11-28 09:01:16 84 ## 13 2024-11-28 09:01:21 81 ## 14 2024-11-28 09:01:26 78 ## 15 2024-11-28 09:01:31 74 ``` --- #
Picture it! ``` r ggplot(hr, aes(x = time, y = heart_rate)) + geom_point(alpha = 0.5) + geom_smooth() + xlab(NULL) + ylab("Beats per Minute") + ggtitle("Thanksgiving Heart Rate") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-30-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Try it Out! What do you think this code will do? ``` r steps_intraday <- get_steps_intraday(lubridate::mdy("11/28/2024")) ``` --- #
Try it Out! Let's see! ``` r head(steps_intraday, 15) ``` ``` ## # A tibble: 15 × 2 ## time steps ## <dttm> <dbl> ## 1 2024-11-28 00:00:00 0 ## 2 2024-11-28 00:01:00 0 ## 3 2024-11-28 00:02:00 0 ## 4 2024-11-28 00:03:00 0 ## 5 2024-11-28 00:04:00 0 ## 6 2024-11-28 00:05:00 0 ## 7 2024-11-28 00:06:00 0 ## 8 2024-11-28 00:07:00 0 ## 9 2024-11-28 00:08:00 0 ## 10 2024-11-28 00:09:00 0 ## 11 2024-11-28 00:10:00 0 ## 12 2024-11-28 00:11:00 0 ## 13 2024-11-28 00:12:00 0 ## 14 2024-11-28 00:13:00 0 ## 15 2024-11-28 00:14:00 0 ``` --- #
Picture it! ``` r ggplot(steps_intraday, aes(x = time, y = steps)) + geom_point(alpha = 0.5) + geom_smooth() + xlab(NULL) + ylab("Steps by Minute") + ggtitle("Thanksgiving Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-36-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r ggplot(comparison_day, aes(x = steps, y = heart_rate)) + geom_point() + xlab("Steps per Minute") + ylab("Beats per Minute") + ggtitle("Heart Rate vs. Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-39-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Try it Out! What do you think this code will do? ``` r activity_df <- get_activity_summary(lubridate::mdy("11/28/2024")) ``` --- #
Try it Out! Let's see! ``` r glimpse(activity_df) ``` ``` ## Rows: 1 ## Columns: 12 ## $ date <date> 2024-11-28 ## $ calories_out <dbl> 2450 ## $ activity_calories <dbl> 623 ## $ calories_bmr <dbl> 1613 ## $ active_score <dbl> -1 ## $ steps <dbl> 4927 ## $ sedentary_minutes <dbl> 1310 ## $ lightly_active_minutes <dbl> 87 ## $ fairly_active_minutes <dbl> 25 ## $ very_active_minutes <dbl> 18 ## $ marginal_calories <dbl> 573 ## $ resting_heart_rate <dbl> 59 ``` --- #
Try it Out! What do you think this code will do? ``` r health_df = NULL for (i in 0:60) { new_row = tibble(date = lubridate::mdy("12/01/2024") - i, resting_hr = get_activity_summary(date)$resting_heart_rate, steps = get_activity_summary(date)$steps ) health_df <- health_df %>% bind_rows(new_row) } ``` --- #
Try it Out! Let's see! ``` r head(health_df, 15) ``` ``` ## # A tibble: 15 × 3 ## date resting_hr steps ## <date> <dbl> <dbl> ## 1 2024-12-01 61 8648 ## 2 2024-11-30 NA 6436 ## 3 2024-11-29 NA 10361 ## 4 2024-11-28 59 4927 ## 5 2024-11-27 NA 5505 ## 6 2024-11-26 NA 5596 ## 7 2024-11-25 NA 8504 ## 8 2024-11-24 58 5958 ## 9 2024-11-23 58 3793 ## 10 2024-11-22 NA 5913 ## 11 2024-11-21 59 9340 ## 12 2024-11-20 59 7895 ## 13 2024-11-19 NA 8120 ## 14 2024-11-18 59 4123 ## 15 2024-11-17 NA 12815 ``` --- #
Picture it! ``` r ggplot(health_df, aes(x = date, y = resting_hr)) + geom_point() + geom_smooth() + xlab(NULL) + ylab("Beats per Minute while Resting") + ggtitle("Resting Heart Rate") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-48-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r ggplot(health_df, aes(x = steps, y = resting_hr)) + geom_point() + geom_smooth() + xlab("Daily Steps") + scale_x_continuous(labels = scales::comma) + ylab("Beats per Minute while Resting") + ggtitle("Resting Heart Rate vs. Daily Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-50-1.png" width="75%" style="display: block; margin: auto;" /> --- #
Picture it! ``` r ggplot(health_df, aes(x = steps, y = resting_hr)) + geom_point() + geom_smooth() + xlim(0, 15000) + scale_x_continuous(label = scales::comma) + xlab("Daily Steps") + ylim(0, 70) + ylab("Beats per Minute while Resting") + ggtitle("Resting Heart Rate vs. Daily Steps") + theme_bw() ``` <img src="index_files/figure-html/unnamed-chunk-52-1.png" width="75%" style="display: block; margin: auto;" /> --- class: inverse, center, middle #
<br><br> Next Steps --- #
Next Steps -- - Download a copy of this repository: https://github.com/bretsw/nursing24-workshop -- - If you have a Fitbit, see if you can retrieve and analyze your own data. -- - Regardless, use the saved data in the `data` folder to play around a bit more, changing different parameters. -- <hr> ### Reflect: -- - What other comparisons might you make? -- - How else might you analyze these Fitbit data? -- - What data sources might you explore in your professional context? --- class: inverse, center, middle #
<br><br> Appendix: <br> Helpful Resources <br> and Troubleshooting --- #
Resources **Beginners:** - [RStudio Beginners' Guide](https://education.rstudio.com/learn/beginner/) - Book: [*Data Science in Education Using R*](https://datascienceineducation.com) - [Physical copy of DSIEUR](https://www.routledge.com/Data-Science-in-Education-Using-R/Estrellado-Freer-Mostipak-Rosenberg-Velasquez/p/book/9780367422257) - [Even more resources from DSIEUR](https://datascienceineducation.com/c18.html) <hr> **Intermediates:** - [RStudio Intermediates' Guide](https://education.rstudio.com/learn/intermediate/) - Book: [*R for Data Science*](https://r4ds.had.co.nz/) <hr> **Experts:** - [RStudio Experts' Guide](https://education.rstudio.com/learn/expert/) - Book: [*Data Analysis in Medicine and Health using R*](https://bookdown.org/drki_musa/dataanalysis/) - Book: [*Learning Statistics with R*](https://learningstatisticswithr.com/) --- #
Troubleshooting - Try to find out what the specific problem is: - Identify what is *not* causing the problem - "Unplug and plug it back in" - restart R; close and reopen R - Seek out workshops and other learning opportunities - Reach out to others! Sharing what is causing an issue can often help to clarify the problem - [Posit Community forum](https://forum.posit.co/) (highly recommended!) - [Contact Bret!](https://bretsw.com) - Describe your woes to a GenAI chatbot (e.g., ChatGPT) - General strategies on learning more: [Chapter 17 of *Data Science in Education Using R*](https://datascienceineducation.com/c17.html) --- class: inverse, center, middle #
<br><br> Questions <hr>
[bret.staudtwillet@fsu.edu](mailto:bret.staudtwillet@fsu.edu) |
[bretsw.com](https://bretsw.com) |
[GitHub](https://github.com/bretsw/) <hr>
Slides: [bretsw.com/nursing24-workshop](https://bretsw.com/nursing24-workshop)
Source Materials: [github.com/bretsw/nursing24-workshop](https://github.com/bretsw/nursing24-workshop)
Workbook: [github.com/bretsw/nursing24-workshop/blob/main/index.Rmd](https://github.com/bretsw/nursing24-workshop/blob/main/workbook.Rmd)