REDCapCAST/articles/REDCapCAST.md

357 lines
80 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# REDCapCAST
``` r
library(REDCapCAST)
```
This vignette covers the basics to get you started with the two basic
features of REDCapCAST:
- Casting REDCap metadata to create a new REDCap database or extend an
existing with a new instrument
- Reading REDCap data in a convenient and focused way, by only getting
the data you need, while preserving as much metadata as possible.
## Casting meta data
The easiest way is to use the
[`shiny_cast()`](https://agdamsbo.github.io/REDCapCAST/reference/shiny_cast.md).
You can access a [hosted version
here](https://agdamsbo.shinyapps.io/redcapcast/) or launch it locally
like this:
``` r
shiny_cast()
```
## Reading data from REDCap
To get you started, the easiest way possible, you can use the
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
function (example below).
You will need an API-key for your REDCap server, the uri/URL/address for
the API connection (usually the address used for accessing your
institutions REDCap server, with an appended “/api/”).
This function includes a few convenience features to ease your further
work.
If your project uses repeating instruments possible as a longitudinal
project, you can choose to widen the data. If not, the result will be a
list of each instrument you have chosen to extract data from. Make sure
to specify only the fields or instruments you need, and avoid to save
any of the data locally, but always source from REDCap to avoid possibly
insecure local storage of sensitive data.
``` r
easy_redcap(
uri = "YOUR URI",
project.name = "MY_PROJECT",
widen.data = TRUE,
fields = c("record_id", "OTHER FIELDS")
)
```
## Splitting the dataset
The
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
function does a few things under the hood. Below are a few examples to
show how the nicely formatted output is achieved.
A sample dataset and Data Dictionary/metadata is provided for this
demonstration:
``` r
redcapcast_data |> gt::gt()
```
| record_id | redcap_event_name | redcap_repeat_instrument | redcap_repeat_instance | cpr | inclusion | inclusion_time | dob | age | age_integer | sex | cohabitation | hypertension | diabetes | region | baseline_data_start_complete | mrs_assessed | mrs_date | mrs_score | mrs_complete | con_mrs | con_calc | consensus_complete | event_datetime | event_age | event_type | new_event_complete |
|-----------|-------------------|--------------------------|------------------------|------------|------------|----------------|------------|-----------|-------------|--------|--------------|--------------|----------|--------|------------------------------|--------------|------------|-----------|--------------|---------|----------|--------------------|---------------------|-----------|------------|--------------------|
| 1 | inclusion | NA | NA | 1203401OB4 | 2023-03-13 | 12:38:49 | 1940-03-12 | 83.00239 | 83 | female | Yes | No | Yes | East | Incomplete | Yes | 2023-03-13 | 1 | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 2 | inclusion | NA | NA | 0102342303 | 2023-03-01 | 10:38:57 | 1934-02-01 | 89.07780 | 89 | male | Yes | No | No | South | Incomplete | Yes | 2023-03-07 | 1 | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 2 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2023-03-09 | 3 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 2 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:49:42 | NA | TIA | Incomplete |
| 3 | inclusion | NA | NA | 2301569823 | 2022-03-08 | 12:01:07 | 1956-01-23 | 66.12319 | 66 | male | No | Yes | Yes | North | Incomplete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 3 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2022-08-16 | 2 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 3 | follow2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2023-03-13 | 1 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 3 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:49:58 | NA | AIS | Incomplete |
| 3 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:01 | NA | ICH | Incomplete |
| 3 | follow2 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:05 | NA | ICH | Incomplete |
| 3 | follow2 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:07 | NA | TIA | Incomplete |
| 3 | follow2 | New Event (?) | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:09 | NA | AIS | Incomplete |
| 4 | inclusion | NA | NA | 0204051342 | 2023-03-14 | 20:39:19 | 1905-04-02 | 117.94903 | 117 | female | NA | NA | NA | NA | Incomplete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 4 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 4 | follow2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 4 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2001-04-11 08:39:05 | 96 | TIA | Complete |
| 4 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2010-04-11 08:39:25 | 105 | TIA | Complete |
| 4 | follow2 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:19 | 118 | AIS | Complete |
| 4 | follow2 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:22 | 118 | ICH | Incomplete |
| 4 | follow2 | New Event (?) | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:24 | 118 | Unknown | Complete |
| 5 | inclusion | NA | NA | 0201976043 | 2023-03-23 | 08:50:31 | 1897-01-02 | 126.21751 | 126 | male | No | Yes | Yes | East | Complete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 5 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 5 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-04-11 09:00:33 | 127 | AIS | Complete |
| 5 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-04-11 09:00:41 | 127 | ICH | Complete |
| 6 | inclusion | NA | NA | 1202320122 | 2024-01-25 | 08:49:28 | 1932-02-12 | 91.95261 | 91 | female | No | Yes | No | East | Complete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
``` r
redcapcast_meta |> gt::gt()
```
| field_name | form_name | section_header | field_type | field_label | select_choices_or_calculations | field_note | text_validation_type_or_show_slider_number | text_validation_min | text_validation_max | identifier | branching_logic | required_field | custom_alignment | question_number | matrix_group_name | matrix_ranking | field_annotation |
|----------------|---------------------|--------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------------------------------------------|---------------------|---------------------|------------|-----------------|----------------|------------------|-----------------|-------------------|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| record_id | baseline_data_start | NA | text | ID | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| cpr | baseline_data_start | NA | text | CPR (Danish civil registration number) | NA | ddmmyyxxxx | NA | NA | NA | y | NA | y | NA | NA | NA | NA | NA |
| inclusion | baseline_data_start | NA | text | Inclusion date | NA | NA | date_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| inclusion_time | baseline_data_start | NA | text | Inclusion time | NA | NA | time_hh_mm_ss | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| dob | baseline_data_start | NA | text | Date of birth (From CPR) | NA | NA | date_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[cpr\]!="", concat(if(mid(\[cpr\], 7, 1)\>=0 and mid(\[cpr\], 7, 1)\<=3,19, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=36 and mid(\[cpr\], 7, 1)\>=4 and mid(\[cpr\], 7, 1)\<=4,20, if(mid(\[cpr\], 5, 2)\>=37 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=4 and mid(\[cpr\], 7, 1)\<=4,19, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=5 and mid(\[cpr\], 7, 1)\<=5,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=5 and mid(\[cpr\], 7, 1)\<=5,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=6 and mid(\[cpr\], 7, 1)\<=6,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=6 and mid(\[cpr\], 7, 1)\<=6,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=7 and mid(\[cpr\], 7, 1)\<=7,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=7 and mid(\[cpr\], 7, 1)\<=7,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=8 and mid(\[cpr\], 7, 1)\<=8,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=8 and mid(\[cpr\], 7, 1)\<=8,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=36 and mid(\[cpr\], 7, 1)\>=9 and mid(\[cpr\], 7, 1)\<=9,20, if(mid(\[cpr\], 5, 2)\>=37 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=9 and mid(\[cpr\], 7, 1)\<=9,19,17))))))))))))), mid(\[cpr\], 5, 2), "-",mid(\[cpr\],3, 2), "-", left(\[cpr\], 2) ), "")) |
| age | baseline_data_start | NA | calc | Age Note: Apparently, the build in datediff() function does not handle counting whole years. This results in wrongly counting age higher around the date of birth. | if(\[cpr\]!="" and \[inclusion\]!="", datediff(\[dob\], \[inclusion\], 'y'), "") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| age_integer | baseline_data_start | NA | calc | Age integer Note: as opposed to the build in datediff() this handles counting years as integers very well. Calculate decimal years in statistical programming software. In R you can use with(ds, stRoke::age_calc(dob, inclusion)). | if(\[cpr\]!="", left(\[inclusion\], 4)-left(\[dob\], 4) - if(mid(\[dob\], 6, 2) \< mid(\[inclusion\], 6, 2) or (mid(\[dob\], 6, 2) = mid(\[inclusion\], 6, 2) and mid(\[dob\], 9, 2) \<= mid(\[inclusion\], 9, 2)), 0, 1),"") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| sex | baseline_data_start | NA | text | Legal sex | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[cpr\]!="",if((right(\[cpr\],1)=1 or right(\[cpr\],1)=3 or right(\[cpr\],1)=5 or right(\[cpr\],1)=7 or right(\[cpr\],1)=9),"male","female"),"")) |
| cohabitation | baseline_data_start | History and social | radio | Cohabitation | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| hypertension | baseline_data_start | NA | radio | Hypertension | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| diabetes | baseline_data_start | NA | radio | Diabetes | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| region | baseline_data_start | Area | dropdown | Region | 1, North \| 2, East \| 3, South \| 4, West | NA | autocomplete | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_assessed | mrs | NA | radio | Assesed | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_date | mrs | NA | text | Assessment date | NA | NA | date_dmy | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_score | mrs | NA | radio | mRS score | 0, 0 \| 1, 1 \| 2, 2 \| 3, 3 \| 4, 4 \| 5, 5 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| con_event_note | consensus | NA | descriptive | \[follow1_arm_1\]\[event_type\]\[1\] : \[follow1_arm_1\]\[event_type\]\[2\] | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| con_mrs | consensus | NA | text | Same event type | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @IF('\[follow1_arm_1\]\[event_type\]\[1\]'='\[follow1_arm_1\]\[event_type\]\[2\]',@DEFAULT='pass',@DEFAULT="fail") |
| con_calc | consensus | NA | text | calc | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[follow1_arm_1\]\[event_type\]\[1\]=\[follow1_arm_1\]\[event_type\]\[2\],\[follow1_arm_1\]\[event_type\]\[1\],"fail")) |
| event_datetime | new_event | NA | text | Time of event | NA | NA | datetime_seconds_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| event_age | new_event | NA | calc | Age at event | if(\[event_datetime\]!="", left(\[event_datetime\], 4)-left(\[inclusion_arm_1\]\[dob\], 4) - if(mid(\[inclusion_arm_1\]\[dob\], 6, 2) \< mid(\[event_datetime\], 6, 2) or (mid(\[inclusion_arm_1\]\[dob\], 6, 2) = mid(\[event_datetime\], 6, 2) and mid(\[inclusion_arm_1\]\[dob\], 9, 2) \<= mid(\[event_datetime\], 9, 2)), 0, 1),"") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| event_type | new_event | NA | radio | Neurovascular event | 1, TIA \| 2, AIS \| 3, ICH \| 4, SAH \| 99, Unknown | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
To save the metadata as labels in the dataset, we can save field labels
and the choices from radio buttons and dropdown features:
``` r
labelled_data <-
apply_field_label(
data = redcapcast_data,
meta = redcapcast_meta
) |>
apply_factor_labels(meta = redcapcast_meta)
```
The `REDCap_split` function splits the data set into a list of
data.frames.
``` r
list <-
REDCap_split(
records = labelled_data,
metadata = redcapcast_meta,
forms = "all"
) |>
# Next steps cleans up and removes generic columns
sanitize_split()
str(list)
#> List of 3
#> $ baseline_data_start: tibble [6 × 14] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:6] 1 2 3 4 5 6
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name : chr [1:6] "inclusion" "inclusion" "inclusion" "inclusion" ...
#> ..$ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> .. ..- attr(*, "label")= chr "CPR (Danish civil registration number)"
#> ..$ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> ..$ inclusion_time : 'hms' num [1:6] 12:38:49 10:38:57 12:01:07 20:39:19 ...
#> .. ..- attr(*, "units")= chr "secs"
#> ..$ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> ..$ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> .. ..- attr(*, "label")= chr "Age\r\nNote: Apparently, the build in datediff() function does not handle counting whole years. This results in"| __truncated__
#> ..$ age_integer : num [1:6] 83 89 66 117 126 91
#> .. ..- attr(*, "label")= chr "Age integer\r\nNote: as opposed to the build in datediff() this handles counting years as integers very well. C"| __truncated__
#> ..$ sex : chr [1:6] "female" "male" "male" "female" ...
#> .. ..- attr(*, "label")= chr "Legal sex"
#> ..$ cohabitation : 'labelled' chr [1:6] "Yes" "Yes" "No" NA ...
#> .. ..- attr(*, "label")= chr "Cohabitation"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ hypertension : 'labelled' chr [1:6] "No" "No" "Yes" NA ...
#> .. ..- attr(*, "label")= chr "Hypertension"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ diabetes : 'labelled' chr [1:6] "Yes" "No" "Yes" NA ...
#> .. ..- attr(*, "label")= chr "Diabetes"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ region : 'labelled' chr [1:6] "East" "South" "North" NA ...
#> .. ..- attr(*, "label")= chr "Region"
#> .. ..- attr(*, "labels")= Named chr [1:4] "1" "2" "3" "4"
#> .. .. ..- attr(*, "names")= chr [1:4] "North" "East" "South" "West"
#> ..$ baseline_data_start_complete: chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs : tibble [5 × 6] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:5] 1 2 2 3 3
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name: chr [1:5] "inclusion" "inclusion" "follow1" "follow1" ...
#> ..$ mrs_assessed : 'labelled' chr [1:5] "Yes" "Yes" "Yes" "Yes" ...
#> .. ..- attr(*, "label")= chr "Assesed"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ mrs_date : Date[1:5], format: "2023-03-13" "2023-03-07" ...
#> ..$ mrs_score : 'labelled' num [1:5] 1 1 3 2 1
#> .. ..- attr(*, "label")= chr "mRS score"
#> .. ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> ..$ mrs_complete : chr [1:5] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ new_event : tibble [13 × 8] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:13] 2 3 3 3 3 3 4 4 4 4 ...
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name : chr [1:13] "follow1" "follow1" "follow1" "follow2" ...
#> ..$ redcap_repeat_instrument: chr [1:13] "new_event" "new_event" "new_event" "new_event" ...
#> ..$ redcap_repeat_instance : num [1:13] 1 1 2 1 2 3 1 2 1 2 ...
#> ..$ event_datetime : POSIXct[1:13], format: "2024-01-18 12:49:42" "2024-01-18 12:49:58" ...
#> ..$ event_age : num [1:13] NA NA NA NA NA NA 96 105 118 118 ...
#> .. ..- attr(*, "label")= chr "Age at event"
#> ..$ event_type : 'labelled' chr [1:13] "TIA" "AIS" "ICH" "ICH" ...
#> .. ..- attr(*, "label")= chr "Neurovascular event"
#> .. ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> ..$ new_event_complete : chr [1:13] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
```
The
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
will then (optionally) continue to widen the data, by transforming the
list of data.frames to a single data.frame with one row for each
subject/record_id (wide data format):
``` r
wide_data <- redcap_wider(list,
event.glue = "{.value}____{redcap_event_name}",
inst.glue = "{.value}____{redcap_repeat_instance}"
)
#> Joining with `by = join_by(record_id)`
#> Joining with `by = join_by(record_id)`
wide_data |> str()
#> tibble [6 × 49] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:6] 1 2 3 4 5 6
#> ..- attr(*, "label")= chr "ID"
#> $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> ..- attr(*, "label")= chr "CPR (Danish civil registration number)"
#> $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:6] 12:38:49 10:38:57 12:01:07 20:39:19 ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> ..- attr(*, "label")= chr "Age\r\nNote: Apparently, the build in datediff() function does not handle counting whole years. This results in"| __truncated__
#> $ age_integer : num [1:6] 83 89 66 117 126 91
#> ..- attr(*, "label")= chr "Age integer\r\nNote: as opposed to the build in datediff() this handles counting years as integers very well. C"| __truncated__
#> $ sex : chr [1:6] "female" "male" "male" "female" ...
#> ..- attr(*, "label")= chr "Legal sex"
#> $ cohabitation : 'labelled' chr [1:6] "Yes" "Yes" "No" NA ...
#> ..- attr(*, "label")= chr "Cohabitation"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ hypertension : 'labelled' chr [1:6] "No" "No" "Yes" NA ...
#> ..- attr(*, "label")= chr "Hypertension"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ diabetes : 'labelled' chr [1:6] "Yes" "No" "Yes" NA ...
#> ..- attr(*, "label")= chr "Diabetes"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ region : 'labelled' chr [1:6] "East" "South" "North" NA ...
#> ..- attr(*, "label")= chr "Region"
#> ..- attr(*, "labels")= Named chr [1:4] "1" "2" "3" "4"
#> .. ..- attr(*, "names")= chr [1:4] "North" "East" "South" "West"
#> $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs_assessed____inclusion : 'labelled' chr [1:6] "Yes" "Yes" NA NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_assessed____follow1 : 'labelled' chr [1:6] NA "Yes" "Yes" NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_assessed____follow2 : 'labelled' chr [1:6] NA NA "Yes" NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_date____inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_date____follow1 : Date[1:6], format: NA "2023-03-09" ...
#> $ mrs_date____follow2 : Date[1:6], format: NA NA ...
#> $ mrs_score____inclusion : 'labelled' num [1:6] 1 1 NA NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_score____follow1 : 'labelled' num [1:6] NA 3 2 NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_score____follow2 : 'labelled' num [1:6] NA NA 1 NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_complete____inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_complete____follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...
#> $ mrs_complete____follow2 : chr [1:6] NA NA "Incomplete" NA ...
#> $ event_datetime____1____follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...
#> $ event_datetime____1____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____1____follow1 : num [1:6] NA NA NA 96 127 NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____1____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_type____1____follow1 : 'labelled' chr [1:6] NA "TIA" "AIS" "TIA" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____1____follow2 : 'labelled' chr [1:6] NA NA "ICH" "AIS" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ new_event_complete____1____follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...
#> $ new_event_complete____1____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ event_datetime____2____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____2____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____2____follow1 : num [1:6] NA NA NA 105 127 NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____2____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____3____follow1 : num [1:6] NA NA NA NA NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____3____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_type____2____follow1 : 'labelled' chr [1:6] NA NA "ICH" "TIA" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____2____follow2 : 'labelled' chr [1:6] NA NA "TIA" "ICH" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____3____follow1 : 'labelled' chr [1:6] NA NA NA NA ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____3____follow2 : 'labelled' chr [1:6] NA NA "AIS" "Unknown" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ new_event_complete____2____follow1: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ new_event_complete____2____follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...
#> $ new_event_complete____3____follow1: chr [1:6] NA NA NA NA ...
#> $ new_event_complete____3____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
```
Transfer suffixes to labels:
``` r
wide_data_suffixes <- wide_data |> suffix2label()
```
## Creating a nice table
``` r
wide_data_suffixes |>
as_factor()|>
dplyr::select(sex, hypertension, diabetes,mrs_score____follow2) |>
gtsummary::tbl_summary(type = gtsummary::all_dichotomous() ~ "categorical")
```
[TABLE]