The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Introduction

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_splitfunction 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" ...

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.