Making analysts lives easier through the power of tidy tibbles
8/18/22

quarto today1
https://events.linuxfoundation.org/r-medicine/
Discount Code: RMED22CHOP for 10% off!
R/Medicine 101: Intro to R for Clinical Data
Should we Teach Data Science to Physicians-in-Training?
In today’s talk we will:
REDCapR as an extraction tool for the API 🔌REDCapTidieR to make our lives easier 🧹What you need:

Record Status Dashboard 
Front-End Data Entry UI 
REDCap functions as a large data table, but data distribution can be complex depending on architectural choices.
Repeating instances can create headaches on the backend.
Open source dataset from SuperHeroDB and available on Kaggle. It contains two tables:
TRUE/FALSE for specific powers)Some core REDCapR functions:
redcap_read_oneshotredcap_metadata_readredcap_event_instruments
v1.1.0Requirements:

# Load applicable libraries:
library(dplyr)
library(REDCapR)
superheroes_db <- redcap_read_oneshot(redcap_uri, token, verbose = FALSE)$data
superheroes_db %>%
glimpse()Rows: 6,700
Columns: 16
$ record_id <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, …
$ redcap_repeat_instrument <chr> NA, "super_hero_powers", "super_hero_power…
$ redcap_repeat_instance <dbl> NA, 1, 2, 3, 4, 5, 6, 7, NA, 1, 2, 3, 4, 5…
$ name <chr> "A-Bomb", NA, NA, NA, NA, NA, NA, NA, "Abe…
$ gender <chr> "Male", NA, NA, NA, NA, NA, NA, NA, "Male"…
$ eye_color <chr> "yellow", NA, NA, NA, NA, NA, NA, NA, "blu…
$ race <chr> "Human", NA, NA, NA, NA, NA, NA, NA, "Icth…
$ hair_color <chr> "No Hair", NA, NA, NA, NA, NA, NA, NA, "No…
$ height <dbl> 203, NA, NA, NA, NA, NA, NA, NA, 191, NA, …
$ weight <dbl> 441, NA, NA, NA, NA, NA, NA, NA, 65, NA, N…
$ publisher <chr> "Marvel Comics", NA, NA, NA, NA, NA, NA, N…
$ skin_color <chr> "-", NA, NA, NA, NA, NA, NA, NA, "blue", N…
$ alignment <chr> "good", NA, NA, NA, NA, NA, NA, NA, "good"…
$ heroes_information_complete <dbl> 0, NA, NA, NA, NA, NA, NA, NA, 0, NA, NA, …
$ power <chr> NA, "Accelerated Healing", "Durability", "…
$ super_hero_powers_complete <dbl> NA, 0, 0, 0, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0…
Remember redcap_repeat_instrument and redcap_repeat_instance, they’re coming back!
| record_id | redcap_repeat_instrument | redcap_repeat_instance | name | gender | eye_color | race | hair_color | height | weight | publisher | skin_color | alignment | heroes_information_complete | power | super_hero_powers_complete |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NA | NA | A-Bomb | Male | yellow | Human | No Hair | 203 | 441 | Marvel Comics | - | good | 0 | NA | NA |
| 0 | super_hero_powers | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Accelerated Healing | 0 |
| 0 | super_hero_powers | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Durability | 0 |
| 0 | super_hero_powers | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Longevity | 0 |
| 0 | super_hero_powers | 4 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Super Strength | 0 |
| 0 | super_hero_powers | 5 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Stamina | 0 |
| 0 | super_hero_powers | 6 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Camouflage | 0 |
| 0 | super_hero_powers | 7 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Self-Sustenance | 0 |
| 1 | NA | NA | Abe Sapien | Male | blue | Icthyo Sapien | No Hair | 191 | 65 | Dark Horse Comics | blue | good | 0 | NA | NA |
| 1 | super_hero_powers | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Agility | 0 |
Record Status Dashboard 
Front-End Data Entry UI

| record_id | redcap_repeat_instrument | redcap_repeat_instance | name | power |
|---|---|---|---|---|
| 0 | NA | NA | A-Bomb | NA |
| 0 | super_hero_powers | 1 | NA | Accelerated Healing |
| 0 | super_hero_powers | 2 | NA | Durability |
| 0 | super_hero_powers | 3 | NA | Longevity |
| 0 | super_hero_powers | 4 | NA | Super Strength |
| 0 | super_hero_powers | 5 | NA | Stamina |
| 0 | super_hero_powers | 6 | NA | Camouflage |
| 0 | super_hero_powers | 7 | NA | Self-Sustenance |
record_id,redcap_repeat_instrument, andrecap_repeat_instanceform a compound key.
A compound key is the combination of 2+ columns necessary to identify a row uniquely in a table
REDCapTidieRAt a glance:
REDCapRtibbles
# A tibble: 2 × 10
redcap_form_name redcap_form_label redcap_data redcap_metadata structure
<chr> <chr> <list> <list> <chr>
1 heroes_information Heroes Information <tibble> <tibble [11 × 17]> nonrepea…
2 super_hero_powers Super Hero Powers <tibble> <tibble [2 × 17]> repeating
# ℹ 5 more variables: data_rows <int>, data_cols <int>, data_size <lbstr_by>,
# data_na_pct <formttbl>, form_complete_pct <formttbl>
Non-Repeating Hero Information
| record_id | redcap_form_instance | power | form_status_complete |
|---|---|---|---|
| 0 | 1 | Accelerated Healing | Incomplete |
| 0 | 2 | Durability | Incomplete |
| 0 | 3 | Longevity | Incomplete |
| 0 | 4 | Super Strength | Incomplete |
| 0 | 5 | Stamina | Incomplete |
| 0 | 6 | Camouflage | Incomplete |
| 0 | 7 | Self-Sustenance | Incomplete |
| 1 | 1 | Agility | Incomplete |
| 1 | 2 | Accelerated Healing | Incomplete |
| 1 | 3 | Cold Resistance | Incomplete |
Repeating Hero Powers
| record_id | name | gender | eye_color | race | hair_color | height | weight | publisher | skin_color | alignment | form_status_complete |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A-Bomb | Male | yellow | Human | No Hair | 203 | 441 | Marvel Comics | - | good | Incomplete |
| 1 | Abe Sapien | Male | blue | Icthyo Sapien | No Hair | 191 | 65 | Dark Horse Comics | blue | good | Incomplete |
| 2 | Abin Sur | Male | blue | Ungaran | No Hair | 185 | 90 | DC Comics | red | good | Incomplete |
| 3 | Abomination | Male | green | Human / Radiation | No Hair | 203 | 441 | Marvel Comics | - | bad | Incomplete |
| 4 | Abraxas | Male | blue | Cosmic Entity | Black | -99 | -99 | Marvel Comics | - | bad | Incomplete |
| 5 | Absorbing Man | Male | blue | Human | No Hair | 193 | 122 | Marvel Comics | - | bad | Incomplete |
| 6 | Adam Monroe | Male | blue | - | Blond | -99 | -99 | NBC - Heroes | - | good | Incomplete |
| 7 | Adam Strange | Male | blue | Human | Blond | 185 | 88 | DC Comics | - | good | Incomplete |
| 8 | Agent 13 | Female | blue | - | Blond | 173 | 61 | Marvel Comics | - | good | Incomplete |
| 9 | Agent Bob | Male | brown | Human | Brown | 178 | 81 | Marvel Comics | - | good | Incomplete |
Non-Repeating Hero Information
| record_id | --- | form_status_complete |
|---|---|---|
| 0 | ... | Incomplete |
| 0 | ... | Incomplete |
| 0 | ... | Incomplete |
| 0 | ... | Incomplete |
| 0 | ... | Incomplete |
Change in
*_form_status_completetoform_status_complete
# A tibble: 2 × 10
redcap_form_name redcap_form_label redcap_data redcap_metadata structure
<chr> <chr> <list> <list> <chr>
1 heroes_information Heroes Information <tibble> <tibble [11 × 17]> nonrepea…
2 super_hero_powers Super Hero Powers <tibble> <tibble [2 × 17]> repeating
# ℹ 5 more variables: data_rows <int>, data_cols <int>, data_size <lbstr_by>,
# data_na_pct <formttbl>, form_complete_pct <formttbl>
bind_tables Direct to EnvironmentThe function:
Clear out our envionrment:
Empty output, no global environment objects
Reload the superheroes_tidy dataset, pipe to bind_tables, check environment:
bind_tables Direct to Environment| Classic | Longitudinal, one arm |
Longitudinal, multi-arm |
|
|---|---|---|---|
| Nonrepeated | record_id |
record_id +redcap_event |
record_id +redcap_event +redcap_arm |
| Repeated | record_id +redcap_repeat_instance |
record_id +redcap_repeat_instance +redcap_event |
record_id +redcap_repeat_instance +redcap_event +redcap_arm |
# A tibble: 3 × 11
redcap_form_name redcap_form_label redcap_data redcap_metadata redcap_events
<chr> <chr> <list> <list> <list>
1 nonrepeated Nonrepeated <tibble> <tibble [3 × 17]> <tibble>
2 nonrepeated2 Nonrepeated2 <tibble> <tibble [3 × 17]> <tibble>
3 repeated Repeated <tibble> <tibble [3 × 17]> <tibble>
# ℹ 6 more variables: structure <chr>, data_rows <int>, data_cols <int>,
# data_size <lbstr_by>, data_na_pct <formttbl>, form_complete_pct <formttbl>
| record_id | redcap_event | redcap_arm | nonrepeat_1 | nonrepeat_2 | form_status_complete |
|---|---|---|---|---|---|
| 1 | event_1 | 1 | 1 | 2 | Incomplete |
| 1 | event_2 | 1 | 1 | 2 | Incomplete |
| 2 | event_1 | 1 | A | B | Incomplete |
| 2 | event_2 | 1 | 5 | 6 | Incomplete |
| 4 | event_1 | 2 | Red | Blue | Incomplete |
| 4 | event_3 | 2 | Green | Yellow | Incomplete |
| record_id | redcap_event | redcap_arm | redcap_form_instance | repeat_1 | repeat_2 | form_status_complete |
|---|---|---|---|---|---|---|
| 1 | event_1 | 1 | 1 | 1 | 2 | Incomplete |
| 1 | event_1 | 1 | 2 | 3 | 4 | Incomplete |
| 1 | event_1 | 1 | 3 | 5 | 6 | Incomplete |
| 1 | event_2 | 1 | 1 | A | B | Incomplete |
| 1 | event_2 | 1 | 2 | C | D | Incomplete |
| 3 | event_1 | 1 | 1 | C | D | Incomplete |
| 3 | event_2 | 1 | 1 | E | F | Incomplete |
| 3 | event_2 | 1 | 2 | G | H | Incomplete |
| 4 | event_3 | 2 | 1 | R1 | R2 | Incomplete |
Install from public GitHub and view the pkgdown site
*REDCapTidieR is in early alpha, but hopefully for not for long!
raw_or_label compatibilityextract_table and extract_tables functionsmetadata <- redcap_metadata_read(redcap_uri, token)$data
metadata %>%
kbl(booktabs = T, escape = F, table.attr = "style='width:20%;'") %>%
# options for HTML output
kable_styling(bootstrap_options = c("striped", "hover", "bordered"),
position = "center",
full_width = F,
font_size = 12,
fixed_thead = T) %>%
column_spec(1, bold = T) %>%
scroll_box(width = "100%", height = "300px")