mirror of
https://github.com/agdamsbo/REDCapCAST.git
synced 2025-12-16 17:42:10 +01:00
357 lines
80 KiB
Markdown
357 lines
80 KiB
Markdown
# 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]
|