Skip to contents

# Introduction

Source: `vignettes/Introduction.Rmd`
`Introduction.Rmd`

    library(REDCapCAST)

This vignette covers the included functions and basic functionality.

A dataset and a meta data file are provided with the package for demonstration of the functions.

## Splitting the dataset

    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 | 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
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
2 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2023-03-09 | 3 | 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 | 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
3 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2022-08-16 | 2 | 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 | NA | NA
3 | follow1 | New Event (?) | 1 | 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 | 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 | 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 | 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 | 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
4 | follow2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | NA | NA
4 | follow2 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:19 | NA | AIS | Complete
4 | follow2 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:22 | NA | ICH | Incomplete
4 | follow2 | New Event (?) | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:24 | NA | 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
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

    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
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
event_date | new_event | NA | text | Date of event | NA | NA | date_dmy | 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

    list <-
      REDCap_split(
        records = redcapcast_data,
        metadata = redcapcast_meta,
        forms = "repeating"
      ) |>
      sanitize_split()
    str(list)
    #> List of 2
    #>  $          : tibble [10 × 17] (S3: tbl_df/tbl/data.frame)
    #>   ..$ record_id                   : num [1:10] 1 2 2 3 3 3 4 4 5 6
    #>   ..$ redcap_event_name           : chr [1:10] "inclusion" "inclusion" "follow1" "inclusion" ...
    #>   ..$ cpr                         : chr [1:10] "1203401OB4" "0102342303" NA "2301569823" ...
    #>   ..$ inclusion                   : Date[1:10], format: "2023-03-13" "2023-03-01" ...
    #>   ..$ dob                         : Date[1:10], format: "1940-03-12" "1934-02-01" ...
    #>   ..$ age                         : num [1:10] 83 89.1 NA 66.1 NA ...
    #>   ..$ age_integer                 : num [1:10] 83 89 NA 66 NA NA 117 NA 126 91
    #>   ..$ sex                         : chr [1:10] "female" "male" NA "male" ...
    #>   ..$ cohabitation                : chr [1:10] "Yes" "Yes" NA "No" ...
    #>   ..$ hypertension                : chr [1:10] "No" "No" NA "Yes" ...
    #>   ..$ diabetes                    : chr [1:10] "Yes" "No" NA "Yes" ...
    #>   ..$ region                      : chr [1:10] "East" "South" NA "North" ...
    #>   ..$ baseline_data_start_complete: chr [1:10] "Incomplete" "Incomplete" NA "Incomplete" ...
    #>   ..$ mrs_assessed                : chr [1:10] "Yes" "Yes" "Yes" NA ...
    #>   ..$ mrs_date                    : Date[1:10], format: "2023-03-13" "2023-03-07" ...
    #>   ..$ mrs_score                   : num [1:10] 1 1 3 NA 2 1 NA NA NA NA
    #>   ..$ mrs_complete                : chr [1:10] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
    #>  $ new_event: tibble [9 × 6] (S3: tbl_df/tbl/data.frame)
    #>   ..$ record_id               : num [1:9] 2 3 3 3 3 3 4 4 4
    #>   ..$ redcap_event_name       : chr [1:9] "follow1" "follow1" "follow1" "follow2" ...
    #>   ..$ redcap_repeat_instrument: chr [1:9] "new_event" "new_event" "new_event" "new_event" ...
    #>   ..$ redcap_repeat_instance  : num [1:9] 1 1 2 1 2 3 1 2 3
    #>   ..$ event_type              : chr [1:9] "TIA" "AIS" "ICH" "ICH" ...
    #>   ..$ new_event_complete      : chr [1:9] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...

    list <-
      REDCap_split(
        records = redcapcast_data,
        metadata = redcapcast_meta,
        forms = "all"
      ) |>
      sanitize_split()
    str(list)
    #> List of 3
    #>  $ baseline_data_start: tibble [6 × 13] (S3: tbl_df/tbl/data.frame)
    #>   ..$ record_id                   : num [1:6] 1 2 3 4 5 6
    #>   ..$ redcap_event_name           : chr [1:6] "inclusion" "inclusion" "inclusion" "inclusion" ...
    #>   ..$ cpr                         : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
    #>   ..$ inclusion                   : Date[1:6], format: "2023-03-13" "2023-03-01" ...
    #>   ..$ dob                         : Date[1:6], format: "1940-03-12" "1934-02-01" ...
    #>   ..$ age                         : num [1:6] 83 89.1 66.1 117.9 126.2 ...
    #>   ..$ age_integer                 : num [1:6] 83 89 66 117 126 91
    #>   ..$ sex                         : chr [1:6] "female" "male" "male" "female" ...
    #>   ..$ cohabitation                : chr [1:6] "Yes" "Yes" "No" NA ...
    #>   ..$ hypertension                : chr [1:6] "No" "No" "Yes" NA ...
    #>   ..$ diabetes                    : chr [1:6] "Yes" "No" "Yes" NA ...
    #>   ..$ region                      : chr [1:6] "East" "South" "North" NA ...
    #>   ..$ 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
    #>   ..$ redcap_event_name: chr [1:5] "inclusion" "inclusion" "follow1" "follow1" ...
    #>   ..$ mrs_assessed     : chr [1:5] "Yes" "Yes" "Yes" "Yes" ...
    #>   ..$ mrs_date         : Date[1:5], format: "2023-03-13" "2023-03-07" ...
    #>   ..$ mrs_score        : num [1:5] 1 1 3 2 1
    #>   ..$ mrs_complete     : chr [1:5] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
    #>  $ new_event          : tibble [9 × 6] (S3: tbl_df/tbl/data.frame)
    #>   ..$ record_id               : num [1:9] 2 3 3 3 3 3 4 4 4
    #>   ..$ redcap_event_name       : chr [1:9] "follow1" "follow1" "follow1" "follow2" ...
    #>   ..$ redcap_repeat_instrument: chr [1:9] "new_event" "new_event" "new_event" "new_event" ...
    #>   ..$ redcap_repeat_instance  : num [1:9] 1 1 2 1 2 3 1 2 3
    #>   ..$ event_type              : chr [1:9] "TIA" "AIS" "ICH" "ICH" ...
    #>   ..$ new_event_complete      : chr [1:9] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...

## Reading data from REDCap

This function wraps all the above demonstrated function to get the dataset, the metadata, apply the `REDCap_split`function and then a bit of cleaning. It just cuts outs all the steps for an easier approach.

The function works very similar to the `REDCapR::redcap_read()` in allowing to specify fields, events and forms for export instead of exporting the whole database and filtering afterwards. I believe this is a better and safer, focused approach.

    # read_redcap_tables(uri = "YOUR URI", token = "YOUR TOKEN")

## Pivotting to wider format

    redcap_wider(list) |> str()
    #> Joining with `by = join_by(record_id)`
    #> Joining with `by = join_by(record_id)`
    #> 'data.frame':    6 obs. of  36 variables:
    #>  $ record_id                   : num  1 2 3 4 5 6
    #>  $ cpr                         : chr  "1203401OB4" "0102342303" "2301569823" "0204051342" ...
    #>  $ inclusion                   : Date, format: "2023-03-13" "2023-03-01" ...
    #>  $ dob                         : Date, format: "1940-03-12" "1934-02-01" ...
    #>  $ age                         : num  83 89.1 66.1 117.9 126.2 ...
    #>  $ age_integer                 : num  83 89 66 117 126 91
    #>  $ sex                         : chr  "female" "male" "male" "female" ...
    #>  $ cohabitation                : chr  "Yes" "Yes" "No" NA ...
    #>  $ hypertension                : chr  "No" "No" "Yes" NA ...
    #>  $ diabetes                    : chr  "Yes" "No" "Yes" NA ...
    #>  $ region                      : chr  "East" "South" "North" NA ...
    #>  $ baseline_data_start_complete: chr  "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
    #>  $ mrs_assessed_inclusion      : chr  "Yes" "Yes" NA NA ...
    #>  $ mrs_assessed_follow1        : chr  NA "Yes" "Yes" NA ...
    #>  $ mrs_assessed_follow2        : chr  NA NA "Yes" NA ...
    #>  $ mrs_date_inclusion          : Date, format: "2023-03-13" "2023-03-07" ...
    #>  $ mrs_date_follow1            : Date, format: NA "2023-03-09" ...
    #>  $ mrs_date_follow2            : Date, format: NA NA ...
    #>  $ mrs_score_inclusion         : num  1 1 NA NA NA NA
    #>  $ mrs_score_follow1           : num  NA 3 2 NA NA NA
    #>  $ mrs_score_follow2           : num  NA NA 1 NA NA NA
    #>  $ mrs_complete_inclusion      : chr  "Incomplete" "Incomplete" NA NA ...
    #>  $ mrs_complete_follow1        : chr  NA "Incomplete" "Incomplete" NA ...
    #>  $ mrs_complete_follow2        : chr  NA NA "Incomplete" NA ...
    #>  $ event_type_1_follow1        : chr  NA "TIA" "AIS" NA ...
    #>  $ event_type_1_follow2        : chr  NA NA "ICH" "AIS" ...
    #>  $ new_event_complete_1_follow1: chr  NA "Incomplete" "Incomplete" NA ...
    #>  $ new_event_complete_1_follow2: chr  NA NA "Incomplete" "Complete" ...
    #>  $ event_type_2_follow1        : chr  NA NA "ICH" NA ...
    #>  $ event_type_2_follow2        : chr  NA NA "TIA" "ICH" ...
    #>  $ event_type_3_follow1        : chr  NA NA NA NA ...
    #>  $ event_type_3_follow2        : chr  NA NA "AIS" "Unknown" ...
    #>  $ new_event_complete_2_follow1: chr  NA NA "Incomplete" NA ...
    #>  $ new_event_complete_2_follow2: chr  NA NA "Incomplete" "Incomplete" ...
    #>  $ new_event_complete_3_follow1: chr  NA NA NA NA ...
    #>  $ new_event_complete_3_follow2: chr  NA NA "Incomplete" "Complete" ...