This vignette covers the the less-typical uses of REDCapR to interact with REDCap through its API.
There is some information that is specific to a REDCap project, as opposed to an individual operation. This includes the (1) uri of the server, and the (2) token for the user’s project. This is hosted on a machine used in REDCapR’s public test suite, so you can run this example from any computer. Unless tests are running.
Disclaimer: Occasionally we’re asked for a longitudinal dataset to be converted from a “long/tall format” (where typically each row is one observation for a participant) to a “wide format” (where each row is on participant). Usually we advise against it. Besides all the database benefits of a long structure, a wide structure restricts your options with the stat routine. No modern longitudinal analysis procedures (e.g., growth curve models or multilevel/hierarchical models) accept wide. You’re pretty much stuck with repeated measures anova, which is very inflexible for real-world medical-ish analyses. It requires a patient to have a measurement at every time point; otherwise the anova excludes the patient entirely.
However we like going wide to produce visual tables for publications, and here’s one way to do it in R. First retrieve the dataset from REDCap.
library(magrittr);
suppressPackageStartupMessages(requireNamespace("dplyr"))
suppressPackageStartupMessages(requireNamespace("tidyr"))
events_to_retain <- c("dose_1_arm_1", "visit_1_arm_1", "dose_2_arm_1", "visit_2_arm_1")
ds_long <- REDCapR::redcap_read_oneshot(redcap_uri=uri, token=token_longitudinal)$data
#> 18 records and 125 columns were read from REDCap in 0.5 seconds. The http status code was 200.
#> study_id redcap_event_name pmq1 pmq2 pmq3 pmq4
#> 1 100 enrollment_arm_1 NA NA NA NA
#> 2 100 dose_1_arm_1 2 2 1 1
#> 3 100 visit_1_arm_1 1 0 0 0
#> 4 100 dose_2_arm_1 3 1 0 0
#> 5 100 visit_2_arm_1 0 1 0 0
#> 6 100 final_visit_arm_1 NA NA NA NA
#> 7 220 enrollment_arm_1 NA NA NA NA
#> 8 220 dose_1_arm_1 0 1 0 2
#> 9 220 visit_1_arm_1 0 3 1 0
#> 10 220 dose_2_arm_1 1 2 0 1
#> 11 220 visit_2_arm_1 3 4 1 0
#> 12 220 final_visit_arm_1 NA NA NA NA
#> 13 304 enrollment_arm_2 NA NA NA NA
#> 14 304 deadline_to_opt_ou_arm_2 NA NA NA NA
#> 15 304 first_dose_arm_2 0 1 0 0
#> 16 304 first_visit_arm_2 2 0 0 0
#> 17 304 final_visit_arm_2 NA NA NA NA
#> 18 304 deadline_to_return_arm_2 NA NA NA NA
When widening only one variable (e.g., pmq1
), the code’s pretty simple:
ds_wide <-
ds_long %>%
dplyr::select(study_id, redcap_event_name, pmq1) %>%
dplyr::filter(redcap_event_name %in% events_to_retain) %>%
tidyr::spread(key=redcap_event_name, value=pmq1)
ds_wide
#> study_id dose_1_arm_1 dose_2_arm_1 visit_1_arm_1 visit_2_arm_1
#> 1 100 2 3 1 0
#> 2 220 0 1 0 3
When widening more than one variable (e.g., pmq1
- pmq4
), it’s usually easiest to go even longer/taller (e.g., ds_eav
) before reversing direction and going wide:
pattern <- "^(\\w+?)_arm_(\\d)$"
ds_eav <- ds_long %>%
dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4) %>%
dplyr::mutate(
event = sub(pattern, "\\1", redcap_event_name),
arm = as.integer(sub(pattern, "\\2", redcap_event_name))
) %>%
dplyr::select(study_id, event, arm, pmq1, pmq2, pmq3, pmq4) %>%
tidyr::gather(key=key, value=value, pmq1, pmq2, pmq3, pmq4) %>%
dplyr::filter(!(event %in% c(
"enrollment", "final_visit", "deadline_to_return", "deadline_to_opt_ou")
)) %>%
dplyr::mutate( # Simulate correcting for mismatched names across arms:
event = dplyr::recode(event, "first_dose"="dose_1", "first_visit"="visit_1"),
key = paste0(event, "_", key)
) %>%
dplyr::select(-event)
# Show the first 10 rows of the EAV table.
ds_eav %>%
head(10)
#> study_id arm key value
#> 1 100 1 dose_1_pmq1 2
#> 2 100 1 visit_1_pmq1 1
#> 3 100 1 dose_2_pmq1 3
#> 4 100 1 visit_2_pmq1 0
#> 5 220 1 dose_1_pmq1 0
#> 6 220 1 visit_1_pmq1 0
#> 7 220 1 dose_2_pmq1 1
#> 8 220 1 visit_2_pmq1 3
#> 9 304 2 dose_1_pmq1 0
#> 10 304 2 visit_1_pmq1 2
#> study_id arm dose_1_pmq1 dose_1_pmq2 dose_1_pmq3 dose_1_pmq4 dose_2_pmq1
#> 1 100 1 2 2 1 1 3
#> 2 220 1 0 1 0 2 1
#> 3 304 2 0 1 0 0 NA
#> dose_2_pmq2 dose_2_pmq3 dose_2_pmq4 visit_1_pmq1 visit_1_pmq2
#> 1 1 0 0 1 0
#> 2 2 0 1 0 3
#> 3 NA NA NA 2 0
#> visit_1_pmq3 visit_1_pmq4 visit_2_pmq1 visit_2_pmq2 visit_2_pmq3
#> 1 0 0 0 1 0
#> 2 1 0 3 4 1
#> 3 0 0 NA NA NA
#> visit_2_pmq4
#> 1 0
#> 2 0
#> 3 NA
The official cURL site discusses the process of using SSL to verify the server being connected to.
Use the SSL cert file that come with the openssl
package.
cert_location <- system.file("cacert.pem", package="openssl")
if( file.exists(cert_location) ) {
config_options <- list(cainfo=cert_location)
ds_different_cert_file <- redcap_read_oneshot(
redcap_uri = uri,
token = token_simple,
config_options = config_options
)$data
}
#> 5 records and 24 columns were read from REDCap in 0.4 seconds. The http status code was 200.
Force the connection to use SSL=3 (which is not preferred, and possibly insecure).
config_options <- list(sslversion=3)
ds_ssl_3 <- redcap_read_oneshot(
redcap_uri = uri,
token = token_simple,
config_options = config_options
)$data
#> 5 records and 24 columns were read from REDCap in 0.3 seconds. The http status code was 200.
config_options <- list(ssl.verifypeer=FALSE)
ds_no_ssl <- redcap_read_oneshot(
redcap_uri = uri,
token = token_simple,
config_options = config_options
)$data
#> 5 records and 24 columns were read from REDCap in 0.6 seconds. The http status code was 200.
For the sake of documentation and reproducibility, the current report was rendered in the following environment. Click the line below to expand.
Environment
#> ─ Session info ──────────────────────────────────────────────────────────
#> setting value
#> version R version 3.6.1 (2019-07-05)
#> os Ubuntu 18.04.3 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language (EN)
#> collate C
#> ctype en_US.UTF-8
#> tz America/Chicago
#> date 2019-09-22
#>
#> ─ Packages ──────────────────────────────────────────────────────────────
#> package * version date lib source
#> assertthat 0.2.1 2019-03-21 [3] CRAN (R 3.6.0)
#> backports 1.1.4 2019-04-10 [3] CRAN (R 3.6.0)
#> callr 3.3.1 2019-07-18 [3] CRAN (R 3.6.1)
#> checkmate 1.9.4 2019-07-04 [3] CRAN (R 3.6.0)
#> cli 1.1.0 2019-03-19 [3] CRAN (R 3.6.0)
#> colorspace 1.4-1 2019-03-18 [3] CRAN (R 3.6.0)
#> crayon 1.3.4 2017-09-16 [3] CRAN (R 3.6.0)
#> curl 4.1 2019-09-16 [3] CRAN (R 3.6.1)
#> desc 1.2.0 2018-05-01 [3] CRAN (R 3.6.0)
#> devtools 2.2.0.9000 2019-09-21 [3] Github (r-lib/devtools@2765fbe)
#> digest 0.6.21 2019-09-20 [3] CRAN (R 3.6.1)
#> dplyr 0.8.3 2019-07-04 [3] CRAN (R 3.6.0)
#> ellipsis 0.3.0 2019-09-20 [3] CRAN (R 3.6.1)
#> evaluate 0.14 2019-05-28 [3] CRAN (R 3.6.0)
#> fs 1.3.1 2019-05-06 [3] CRAN (R 3.6.0)
#> glue 1.3.1 2019-03-12 [3] CRAN (R 3.6.0)
#> hms 0.5.1 2019-08-23 [3] CRAN (R 3.6.1)
#> htmltools 0.3.6 2017-04-28 [3] CRAN (R 3.6.0)
#> httr 1.4.1 2019-08-05 [3] CRAN (R 3.6.1)
#> kableExtra 1.1.0.9001 2019-05-18 [3] local
#> knitr * 1.25 2019-09-18 [3] CRAN (R 3.6.1)
#> lifecycle 0.1.0 2019-08-01 [3] CRAN (R 3.6.1)
#> magrittr * 1.5 2014-11-22 [3] CRAN (R 3.6.0)
#> memoise 1.1.0 2017-04-21 [3] CRAN (R 3.6.0)
#> munsell 0.5.0 2018-06-12 [3] CRAN (R 3.6.0)
#> pillar 1.4.2 2019-06-29 [3] CRAN (R 3.6.0)
#> pkgbuild 1.0.5 2019-08-26 [3] CRAN (R 3.6.1)
#> pkgconfig 2.0.2 2018-08-16 [3] CRAN (R 3.6.0)
#> pkgload 1.0.2 2018-10-29 [3] CRAN (R 3.6.0)
#> prettyunits 1.0.2 2015-07-13 [3] CRAN (R 3.6.0)
#> processx 3.4.1 2019-07-18 [3] CRAN (R 3.6.1)
#> ps 1.3.0 2018-12-21 [3] CRAN (R 3.6.0)
#> purrr 0.3.2 2019-03-15 [3] CRAN (R 3.6.0)
#> R6 2.4.0 2019-02-14 [3] CRAN (R 3.6.0)
#> Rcpp 1.0.2 2019-07-25 [3] CRAN (R 3.6.1)
#> readr 1.3.1 2018-12-21 [3] CRAN (R 3.6.0)
#> REDCapR * 0.10.2 2019-09-22 [1] local
#> remotes 2.1.0 2019-06-24 [3] CRAN (R 3.6.0)
#> rlang 0.4.0 2019-06-25 [3] CRAN (R 3.6.0)
#> rmarkdown 1.15 2019-08-21 [3] CRAN (R 3.6.1)
#> rprojroot 1.3-2 2018-01-03 [3] CRAN (R 3.6.0)
#> rstudioapi 0.10 2019-03-19 [3] CRAN (R 3.6.0)
#> rvest 0.3.4 2019-05-15 [3] CRAN (R 3.6.0)
#> scales 1.0.0 2018-08-09 [3] CRAN (R 3.6.0)
#> sessioninfo 1.1.1 2018-11-05 [3] CRAN (R 3.6.0)
#> stringi 1.4.3 2019-03-12 [3] CRAN (R 3.6.0)
#> stringr 1.4.0 2019-02-10 [3] CRAN (R 3.6.0)
#> testthat 2.2.1 2019-07-25 [3] CRAN (R 3.6.1)
#> tibble 2.1.3 2019-06-06 [3] CRAN (R 3.6.0)
#> tidyr 1.0.0 2019-09-11 [3] CRAN (R 3.6.1)
#> tidyselect 0.2.5 2018-10-11 [3] CRAN (R 3.6.0)
#> usethis 1.5.1 2019-07-04 [3] CRAN (R 3.6.0)
#> vctrs 0.2.0 2019-07-05 [3] CRAN (R 3.6.0)
#> viridisLite 0.3.0 2018-02-01 [3] CRAN (R 3.6.0)
#> webshot 0.5.1 2018-09-28 [3] CRAN (R 3.6.0)
#> withr 2.1.2 2018-03-15 [3] CRAN (R 3.6.0)
#> xfun 0.9 2019-08-21 [3] CRAN (R 3.6.1)
#> xml2 1.2.2 2019-08-09 [3] CRAN (R 3.6.1)
#> yaml 2.2.0 2018-07-25 [3] CRAN (R 3.6.0)
#> zeallot 0.1.0 2018-01-28 [3] CRAN (R 3.6.0)
#>
#> [1] /tmp/Rtmp8vaOvg/Rinst10c579b5cb6d
#> [2] /tmp/RtmpsgrWgH/temp_libpath7402255995b5
#> [3] /home/wibeasley/R/x86_64-pc-linux-gnu-library/3.6
#> [4] /usr/local/lib/R/site-library
#> [5] /usr/lib/R/site-library
#> [6] /usr/lib/R/library
Report rendered by wibeasley at 2019-09-22, 17:46 -0500 in 2 seconds.