diff --git a/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md b/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md index 2fb86348..3908a715 100644 --- a/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md +++ b/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md @@ -7,19 +7,15 @@ assignees: '' --- -**Describe the behavior** -Please provide a clear and concise description of the scenario and the behavior. *Be careful not to include tokens, PHI (protected health information), or other information that should not be public!* +Thank you for taking the time to file an issue. Here are some suggestions for writing your issue that should let us respond and help you more quickly. -**Troubleshooter Results** -Please carefully reread the [Troubleshooting Vignette](https://ouhscbbmc.github.io/REDCapR/articles/TroubleshootingApiCalls.html) and thoroughly describe which part(s) doesn't work. Many people have contributed to this document; it is likely that it will help precisely identify the location of the problem, which will help us respond with better advice. +**Troubleshooter**: Please carefully reread the [Troubleshooting Vignette](https://ouhscbbmc.github.io/REDCapR/articles/TroubleshootingApiCalls.html) and thoroughly describe which parts don't work. -If you have advice for improving the [Troubleshooter](https://ouhscbbmc.github.io/REDCapR/articles/TroubleshootingApiCalls.html) or [this issue template](https://github.com/OuhscBbmc/REDCapR/blob/master/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md), we'd love to hear about it. +**Describe the behavior**: Please provide a clear and concise description of the scenario and the behavior. *Be careful not to include tokens, PHI (protected health information), or other information that should not be public!* -**Expected behavior** -A clear and concise description of what you expected to happen. -**Screenshots** -If applicable, add screenshots to help explain your problem. +**Expected behavior**: A clear and concise description of what you expected to happen. + **Desktop (please complete the following information):** - OS: [e.g. Windows 10] @@ -27,7 +23,9 @@ If applicable, add screenshots to help explain your problem. - REDCapR Version [e.g. 0.10.2.9005 --run `packageVersion("REDCapR")`] -**Additional context** -Add any other context about the problem here. +**Additional context**: Add any other information about the specific problem, such as a data dictionary or screenshot. + -*Remember, don't include tokens, PHI, or other information that should not be public.* +**Thank you and reminder**: + * Many people have contributed to this package and it's documentation, and it's continually improving. If you have advice for improving the documentation, the [Troubleshooter](https://ouhscbbmc.github.io/REDCapR/articles/TroubleshootingApiCalls.html), or [this issue template](https://github.com/OuhscBbmc/REDCapR/blob/master/.github/ISSUE_TEMPLATE/unexpected-behavior-issue-template.md), we'd love to hear it. + * *Remember, don't include tokens, PHI, or other information that should not be public.* diff --git a/DESCRIPTION b/DESCRIPTION index f654dd0d..af53b451 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -6,7 +6,7 @@ Description: Encapsulates functions to streamline calls from R to the REDCap University. The Application Programming Interface (API) offers an avenue to access and modify data programmatically, improving the capacity for literate and reproducible programming. -Version: 0.10.2.9006 +Version: 0.11.0 Authors@R: c(person("Will", "Beasley", role = c("aut", "cre"), email = "wibeasley@hotmail.com", comment = c(ORCID = "0000-0002-5613-5006")), person("David", "Bard", role = "ctb"), @@ -18,7 +18,8 @@ Authors@R: c(person("Will", "Beasley", role = c("aut", "cre"), email = role = "ctb"), person("Hao", "Zhu", role = "ctb", comment = c(ORCID = '0000-0002-3386-6076')), person("Felix", "Torres", - role = "ctb", email = "fetorres@ucsd.edu")) + role = "ctb", email = "fetorres@ucsd.edu"), person("Philip", "Chase", + role = "ctb", email = "pbc@ufl.edu")) URL: https://github.com/OuhscBbmc/REDCapR, http://ouhsc.edu/bbmc/, http://project-redcap.org BugReports: https://github.com/OuhscBbmc/REDCapR/issues diff --git a/NEWS.md b/NEWS.md index d9493ca2..661dc788 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,7 @@ Upcoming Versions In the future: ... -Version 0.11 (Released ?) +Version 0.11 (Released 2020-04-20) ========================================================== ### Breaking Changes (possible, but unlikely) @@ -25,7 +25,7 @@ Version 0.11 (Released ?) ### Stability Features -* `httr::content()` (which is inside `kernel_api()`) now processes the returned value as "text/csv", by default. This should prevent strange characters from tricking the process as the internal variable `raw_text` is being formed. See the [httr::content()`](https://httr.r-lib.org/reference/content.html) documentation for a list of possible values for the `content_type` parameter. (Thanks to great debugging by @vortexing, #269) +* `httr::content()` (which is inside `kernel_api()`) now processes the returned value as "text/csv", by default. This should prevent strange characters from tricking the process as the internal variable `raw_text` is being formed. See the [httr::content()`](https://httr.r-lib.org/reference/content.html) documentation for a list of possible values for the `content_type` parameter. (Thanks to great debugging by @vortexing #269, @sybandrew #272, & @begavett, #290) * Similarly, `kernel_api()` now has an `encoding` parameter, which defaults to "UTF-8". (#270) diff --git a/R/redcap-download-file-oneshot.R b/R/redcap-download-file-oneshot.R index 61538564..fc2f898d 100644 --- a/R/redcap-download-file-oneshot.R +++ b/R/redcap-download-file-oneshot.R @@ -18,6 +18,13 @@ #' Required #' @param event The name of the event where the file is saved in REDCap. #' Optional +#' @param repeat_instrument The name of the instrument that is repeating +#' for a given event. +#' Optional +#' @param repeat_instance (only for projects with repeating instruments/events) +#' The repeat instance number of the repeating event (if longitudinal) or the +#' repeating instrument (if classic or longitudinal). Default value is '1'. +#' Optional #' @param verbose A boolean value indicating if `message`s should be printed #' to the R console during the operation. Optional. #' @param config_options A list of options to pass to [httr::POST()] method @@ -101,6 +108,8 @@ redcap_download_file_oneshot <- function( record, field, event = "", + repeat_instrument = NULL, + repeat_instance = NULL, verbose = TRUE, config_options = NULL ) { @@ -132,6 +141,14 @@ redcap_download_file_oneshot <- function( if (0L < nchar(event)) post_body$event <- event + if (!is.null(repeat_instrument)) { + if (is.null(repeat_instance)) { + stop("You must specify repeat_instance when specified repeat_instrement"); + } + post_body$repeat_instrument <- repeat_instrument + post_body$repeat_instance <- repeat_instance + } + # This is the first of two important lines in the function. # It retrieves the information from the server and stores it in RAM. kernel <- kernel_api(redcap_uri, post_body, config_options) diff --git a/_pkgdown.yml b/_pkgdown.yml index 541ec157..0c387c97 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -50,6 +50,7 @@ reference: - redcap_next_free_record_name - redcap_metadata_read - redcap_metadata_write + - redcap_survey_link_export_oneshot - redcap_users_export - redcap_variables - redcap_version diff --git a/cran-comments.md b/cran-comments.md index 50d8c1d3..2f801705 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,8 +1,6 @@ Description ----------------------------------------------- -This submission includes new features and also addresses some (soon-to-be) breaking changes in the libraries underneath. - -I have fixed the three points described in your previous response (documented in [our issue](https://github.com/OuhscBbmc/REDCapR/issues/253)). For the first point, I fixed some markdown syntax so the API's url is correctly interpreted. I'm sorry the test builds below didn't uncover the last two. +This submission includes new features and also addresses a recent breaking change from tibble 3.0.0 (https://github.com/OuhscBbmc/REDCapR/issues/302). Thank you for taking the time to review my submission, and please tell me if there's something else I should do for CRAN. -Will Beasley @@ -10,15 +8,15 @@ Thank you for taking the time to review my submission, and please tell me if the Test environments ----------------------------------------------- -1. Local Ubuntu, R 3.6.1 patched -1. Local Win8, R 3.6.1 patched +1. Local Ubuntu, R 3.6.3 patched +1. Local Win8, R 4.0.0 RC 1. r-hub - 1. [Ubuntu Linux 16.04 LTS, R-release, GCC](https://builder.r-hub.io/status/REDCapR_0.10.1.tar.gz-ffc36a958fe44f3fb3263929670f8138) - 1. [Fedora Linux, R-devel, clang, gfortran](https://builder.r-hub.io/status/REDCapR_0.10.1.tar.gz-2e2bed0d3cda44429a8f830c2b9d8e92) - 1. [Windows Server](https://builder.r-hub.io/status/REDCapR_0.10.1.tar.gz-0c79ee0f9b3e49f7b381348e9f7283b0) -1. [win-builder](https://win-builder.r-project.org/a9ub2IBAb24W), development version. + 1. [Ubuntu Linux 16.04 LTS, R-release, GCC](https://builder.r-hub.io/status/REDCapR_0.10.2.9006.tar.gz-71151f2f04454bc18c16430e5d62610b) + 1. [Fedora Linux, R-devel, clang, gfortran](https://builder.r-hub.io/status/REDCapR_0.10.2.9006.tar.gz-2f619028b765442f9dc1c34373443d2a) + 1. [Windows Server](https://builder.r-hub.io/status/REDCapR_0.10.2.9006.tar.gz-80133501925a411da4c3cf3be8205e29) +1. [win-builder](https://win-builder.r-project.org/xYyWrC1uFjXH), development version. 1. [Travis CI](https://travis-ci.org/OuhscBbmc/REDCapR), Ubuntu 14.04 LTS -1. [AppVeyor](https://ci.appveyor.com/project/wibeasley/REDCapR), Windows Server 2012 +1. [AppVeyor](https://ci.appveyor.com/project/wibeasley/REDCapR), Windows Server 2012 R2 R CMD check results diff --git a/docs/404.html b/docs/404.html index 28be2bff..49fa6436 100644 --- a/docs/404.html +++ b/docs/404.html @@ -17,23 +17,27 @@ - + - + - + + + + + - - + + - + - - + + @@ -42,15 +46,14 @@ - + - - + @@ -68,7 +71,7 @@ -
+vignettes/BasicREDCapROperations.Rmd
BasicREDCapROperations.Rmd
There is some information that is specific to the 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.
-library(REDCapR) #Load the package into the current R session.
-uri <- "https://bbmc.ouhsc.edu/redcap/api/"
-token <- "9A81268476645C4E5F03428B8AC3AA7B" #`UnitTestPhiFree` user and simple project (pid 153)
library(REDCapR) # Load the package into the current R session. +uri <- "https://bbmc.ouhsc.edu/redcap/api/" +token <- "9A81268476645C4E5F03428B8AC3AA7B" # `UnitTestPhiFree` user and simple project (pid 153)
If no information is passed about the desired records or fields, then the entire data set is returned. Only two parameters are required, redcap_uri
and token
. Unless the verbose
parameter is set to FALSE
, a message will be printed on the R console with the number of records and fields returned.
#Return all records and all variables.
-ds_all_rows_all_fields <- redcap_read(redcap_uri=uri, token=token)$data
The data dictionary describing 16 fields was read from REDCap in 0.5 seconds. The http status code was 200.
-5 records and 1 columns were read from REDCap in 0.4 seconds. The http status code was 200.
-Starting to read 5 records at 2020-02-18 10:35:33.
+# Return all records and all variables. +ds_all_rows_all_fields <- redcap_read(redcap_uri = uri, token = token)$data
The data dictionary describing 16 fields was read from REDCap in 0.4 seconds. The http status code was 200.
+5 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
+Starting to read 5 records at 2020-04-19 13:31:36.
Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).
-5 records and 24 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+5 records and 24 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
.default = col_double(),
@@ -155,7 +137,7 @@
mugshot = col_character()
)
See spec(...) for full column specifications.
-
+ds_all_rows_all_fields # Inspect the returned dataset
record_id name_first name_last address
1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232
2 2 Tumtum Nutmouse 14 Rose Cottage Blvd.\nKenning UK 34243
@@ -198,18 +180,18 @@
Read a subset of the records
If only a subset of the records is desired, the two approaches are shown below. The first is to pass an array (where each element is an ID) to the records
parameter. The second is to pass a single string (where the elements are separated by commas) to the records_collapsed
parameter.
The first format is more natural for more R users. The second format is what is expected by the REDCap API. If a value for records
is specified, but records_collapsed
is not specified, then redcap_read_oneshot
automatically converts the array into the format needed by the API.
-#Return only records with IDs of 1 and 3
-desired_records_v1 <- c(1, 3)
-ds_some_rows_v1 <- redcap_read(
- redcap_uri = uri,
- token = token,
- records = desired_records_v1
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
-2 records and 1 columns were read from REDCap in 0.3 seconds. The http status code was 200.
-Starting to read 2 records at 2020-02-18 10:35:35.
+# Return only records with IDs of 1 and 3
+desired_records_v1 <- c(1, 3)
+ds_some_rows_v1 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ records = desired_records_v1
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
+2 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
+Starting to read 2 records at 2020-04-19 13:31:37.
Reading batch 1 of 1, with subjects 1 through 3 (ie, 2 unique subject records).
-2 records and 24 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+2 records and 24 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
.default = col_double(),
@@ -223,18 +205,18 @@
mugshot = col_character()
)
See spec(...) for full column specifications.
-#Return only records with IDs of 1 and 3 (alternate way)
-desired_records_v2 <- "1, 3"
-ds_some_rows_v2 <- redcap_read(
- redcap_uri = uri,
- token = token,
- records_collapsed = desired_records_v2
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
-2 records and 1 columns were read from REDCap in 0.7 seconds. The http status code was 200.
-Starting to read 2 records at 2020-02-18 10:35:37.
+# Return only records with IDs of 1 and 3 (alternate way)
+desired_records_v2 <- "1, 3"
+ds_some_rows_v2 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ records_collapsed = desired_records_v2
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
+2 records and 1 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+Starting to read 2 records at 2020-04-19 13:31:38.
Reading batch 1 of 1, with subjects 1 through 3 (ie, 2 unique subject records).
-2 records and 24 columns were read from REDCap in 0.4 seconds. The http status code was 200.
+2 records and 24 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
.default = col_double(),
@@ -248,7 +230,7 @@
mugshot = col_character()
)
See spec(...) for full column specifications.
-
+ds_some_rows_v2 # Inspect the returned dataset
record_id name_first name_last address
1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232
2 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402
@@ -269,43 +251,43 @@
Read a subset of the fields
If only a subset of the fields is desired, then two approaches exist. The first is to pass an array (where each element is an field) to the fields
parameter. The second is to pass a single string (where the elements are separated by commas) to the fields_collapsed
parameter. Like with records
and records_collapsed
described above, this function converts the more natural format (i.e., fields
) to the format required by the API (ie, fields_collapsed
) if fields
is specified and fields_collapsed
is not.
-#Return only the fields record_id, name_first, and age
-desired_fields_v1 <- c("record_id", "name_first", "age")
-ds_some_fields_v1 <- redcap_read(
- redcap_uri = uri,
- token = token,
- fields = desired_fields_v1
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
+#Return only the fields record_id, name_first, and age
+desired_fields_v1 <- c("record_id", "name_first", "age")
+ds_some_fields_v1 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ fields = desired_fields_v1
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
5 records and 1 columns were read from REDCap in 0.3 seconds. The http status code was 200.
-Starting to read 5 records at 2020-02-18 10:35:38.
+Starting to read 5 records at 2020-04-19 13:31:40.
Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).
-5 records and 3 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+5 records and 3 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
record_id = col_double(),
name_first = col_character(),
age = col_double()
)
-#Return only the fields record_id, name_first, and age (alternate way)
-desired_fields_v2 <- "record_id, name_first, age"
-ds_some_fields_v2 <- redcap_read(
- redcap_uri = uri,
- token = token,
- fields_collapsed = desired_fields_v2
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
-5 records and 1 columns were read from REDCap in 0.3 seconds. The http status code was 200.
-Starting to read 5 records at 2020-02-18 10:35:40.
+#Return only the fields record_id, name_first, and age (alternate way)
+desired_fields_v2 <- "record_id, name_first, age"
+ds_some_fields_v2 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ fields_collapsed = desired_fields_v2
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
+5 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
+Starting to read 5 records at 2020-04-19 13:31:41.
Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).
-5 records and 3 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+5 records and 3 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
record_id = col_double(),
name_first = col_character(),
age = col_double()
)
-
+ds_some_fields_v2 #Inspect the returned dataset
record_id name_first age
1 1 Nutmeg 11
2 2 Tumtum 11
@@ -317,51 +299,51 @@
Read a subset of records, conditioned on the values in some variables
The two techniques above can be combined when your datasets are large and you don’t want to pull records with certain values. Suppose you want to select subjects from the previous dataset if the were born before 1960 and their weight was over 70kg. Two calls to the server are required. The first call to REDCap pulls all the records, but for only three columns: record_id
, dob
, and weight
. From this subset, identify the records that you want to pull all the data for; in this case, the desired record_id
values are 3
& 5
. The second call to REDCap pulls all the columns, but only for the identified records.
-######
-## Step 1: First call to REDCap
-desired_fields_v3 <- c("record_id", "dob", "weight")
-ds_some_fields_v3 <- redcap_read(
- redcap_uri = uri,
- token = token,
- fields = desired_fields_v3
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
+######
+## Step 1: First call to REDCap
+desired_fields_v3 <- c("record_id", "dob", "weight")
+ds_some_fields_v3 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ fields = desired_fields_v3
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
5 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
-Starting to read 5 records at 2020-02-18 10:35:41.
+Starting to read 5 records at 2020-04-19 13:31:42.
Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).
-5 records and 3 columns were read from REDCap in 0.4 seconds. The http status code was 200.
+5 records and 3 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
record_id = col_double(),
dob = col_date(format = ""),
weight = col_double()
)
-
+ds_some_fields_v3 #Examine the these three variables.
record_id dob weight
1 1 2003-08-30 1
2 2 2003-03-10 1
3 3 1934-04-09 80
4 4 1952-11-02 54
5 5 1955-04-15 104
-######
-## Step 2: identify desired records, based on age & weight
-before_1960 <- (ds_some_fields_v3$dob <= as.Date("1960-01-01"))
-heavier_than_70_kg <- (ds_some_fields_v3$weight > 70)
-desired_records_v3 <- ds_some_fields_v3[before_1960 & heavier_than_70_kg, ]$record_id
-
-desired_records_v3 #Peek at IDs of the identified records
+######
+## Step 2: identify desired records, based on age & weight
+before_1960 <- (ds_some_fields_v3$dob <= as.Date("1960-01-01"))
+heavier_than_70_kg <- (ds_some_fields_v3$weight > 70)
+desired_records_v3 <- ds_some_fields_v3[before_1960 & heavier_than_70_kg, ]$record_id
+
+desired_records_v3 #Peek at IDs of the identified records
[1] 3 5
-######
-## Step 3: second call to REDCap
-#Return only records that met the age & weight criteria.
-ds_some_rows_v3 <- redcap_read(
- redcap_uri = uri,
- token = token,
- records = desired_records_v3
-)$data
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
-2 records and 1 columns were read from REDCap in 0.4 seconds. The http status code was 200.
-Starting to read 2 records at 2020-02-18 10:35:43.
+######
+## Step 3: second call to REDCap
+#Return only records that met the age & weight criteria.
+ds_some_rows_v3 <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ records = desired_records_v3
+)$data
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
+2 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
+Starting to read 2 records at 2020-04-19 13:31:44.
Reading batch 1 of 1, with subjects 3 through 5 (ie, 2 unique subject records).
2 records and 24 columns were read from REDCap in 0.3 seconds. The http status code was 200.
Parsed with column specification:
@@ -377,7 +359,7 @@
mugshot = col_character()
)
See spec(...) for full column specifications.
-
+ds_some_rows_v3 #Examine the results.
record_id name_first name_last address
1 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402
2 5 John Lee Walker Hotel Suite\nNew Orleans LA, 70115
@@ -410,24 +392,24 @@
- The
fields_collapsed
fields passed to the API. This shows which field subsets, if any, were requested.
- The
elapsed_seconds
measures the duration of the call.
-#Return only the fields record_id, name_first, and age
-all_information <- redcap_read(
- redcap_uri = uri,
- token = token,
- fields = desired_fields_v1
-)
-The data dictionary describing 16 fields was read from REDCap in 0.3 seconds. The http status code was 200.
-5 records and 1 columns were read from REDCap in 0.3 seconds. The http status code was 200.
-Starting to read 5 records at 2020-02-18 10:35:44.
+#Return only the fields record_id, name_first, and age
+all_information <- redcap_read(
+ redcap_uri = uri,
+ token = token,
+ fields = desired_fields_v1
+)
+The data dictionary describing 16 fields was read from REDCap in 0.2 seconds. The http status code was 200.
+5 records and 1 columns were read from REDCap in 0.2 seconds. The http status code was 200.
+Starting to read 5 records at 2020-04-19 13:31:45.
Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).
-5 records and 3 columns were read from REDCap in 0.3 seconds. The http status code was 200.
+5 records and 3 columns were read from REDCap in 0.2 seconds. The http status code was 200.
Parsed with column specification:
cols(
record_id = col_double(),
name_first = col_character(),
age = col_double()
)
-
+all_information #Inspect the additional information
$data
record_id name_first age
1 1 Nutmeg 11
@@ -443,7 +425,7 @@
[1] "200"
$outcome_messages
-[1] "5 records and 3 columns were read from REDCap in 0.3 seconds. The http status code was 200."
+[1] "5 records and 3 columns were read from REDCap in 0.2 seconds. The http status code was 200."
$records_collapsed
[1] ""
@@ -461,7 +443,7 @@
[1] ""
$elapsed_seconds
-[1] 1.400878
+[1] 1.284016
Environment
─ Session info ───────────────────────────────────────────────────────────────
setting value
- version R version 3.6.2 (2019-12-12)
+ version R version 3.6.3 (2020-02-29)
os Ubuntu 19.10
system x86_64, linux-gnu
ui X11
@@ -479,102 +461,76 @@
collate en_US.UTF-8
ctype en_US.UTF-8
tz America/Chicago
- date 2020-02-18
+ date 2020-04-19
─ Packages ───────────────────────────────────────────────────────────────────
package * version date lib source
assertthat 0.2.1 2019-03-21 [2] CRAN (R 3.6.1)
- backports 1.1.5 2019-10-02 [2] CRAN (R 3.6.1)
- callr 3.4.2 2020-02-12 [2] CRAN (R 3.6.2)
+ backports 1.1.6 2020-04-05 [2] CRAN (R 3.6.3)
checkmate 2.0.0 2019-12-03 [2] local
- cli 2.0.1 2020-01-08 [2] CRAN (R 3.6.1)
+ cli 2.0.2 2020-02-28 [2] CRAN (R 3.6.2)
colorspace 1.4-1 2019-03-18 [2] CRAN (R 3.6.1)
crayon 1.3.4 2017-09-16 [2] CRAN (R 3.6.1)
curl 4.3 2019-12-02 [2] CRAN (R 3.6.1)
desc 1.2.0 2018-05-01 [2] CRAN (R 3.6.1)
- devtools 2.2.1 2019-09-24 [2] CRAN (R 3.6.1)
- digest 0.6.24 2020-02-12 [2] CRAN (R 3.6.2)
- dplyr 0.8.4 2020-01-31 [2] CRAN (R 3.6.2)
+ digest 0.6.25 2020-02-23 [2] CRAN (R 3.6.2)
+ dplyr 0.8.5 2020-03-07 [2] CRAN (R 3.6.3)
ellipsis 0.3.0 2019-09-20 [2] CRAN (R 3.6.1)
evaluate 0.14 2019-05-28 [2] CRAN (R 3.6.1)
fansi 0.4.1 2020-01-08 [2] CRAN (R 3.6.1)
- fs 1.3.1 2019-05-06 [2] CRAN (R 3.6.1)
- glue 1.3.1 2019-03-12 [2] CRAN (R 3.6.1)
+ fs 1.4.1 2020-04-04 [2] CRAN (R 3.6.3)
+ glue 1.4.0 2020-04-03 [2] CRAN (R 3.6.3)
hms 0.5.3 2020-01-08 [2] CRAN (R 3.6.1)
htmltools 0.4.0 2019-10-04 [2] CRAN (R 3.6.1)
httr 1.4.1 2019-08-05 [2] CRAN (R 3.6.1)
kableExtra 1.1.0 2019-03-16 [2] CRAN (R 3.6.1)
knitr * 1.28 2020-02-06 [2] CRAN (R 3.6.2)
- lifecycle 0.1.0 2019-08-01 [2] CRAN (R 3.6.1)
+ lifecycle 0.2.0 2020-03-06 [2] CRAN (R 3.6.3)
magrittr * 1.5 2014-11-22 [2] CRAN (R 3.6.1)
MASS 7.3-51.5 2019-12-20 [5] CRAN (R 3.6.2)
memoise 1.1.0 2017-04-21 [2] CRAN (R 3.6.1)
munsell 0.5.0 2018-06-12 [2] CRAN (R 3.6.1)
pillar 1.4.3 2019-12-20 [2] CRAN (R 3.6.1)
- pkgbuild 1.0.6 2019-10-09 [2] CRAN (R 3.6.1)
pkgconfig 2.0.3 2019-09-22 [2] CRAN (R 3.6.1)
- pkgdown 1.4.1 2019-09-15 [2] CRAN (R 3.6.1)
- pkgload 1.0.2 2018-10-29 [2] CRAN (R 3.6.1)
- prettyunits 1.1.1 2020-01-24 [2] CRAN (R 3.6.2)
- processx 3.4.2 2020-02-09 [2] CRAN (R 3.6.2)
- ps 1.3.2 2020-02-13 [2] CRAN (R 3.6.2)
+ pkgdown 1.5.0 2020-03-25 [2] CRAN (R 3.6.3)
purrr 0.3.3 2019-10-18 [2] CRAN (R 3.6.1)
R6 2.4.1 2019-11-12 [2] CRAN (R 3.6.1)
- Rcpp 1.0.3 2019-11-08 [2] CRAN (R 3.6.1)
+ Rcpp 1.0.4 2020-03-17 [2] CRAN (R 3.6.3)
readr 1.3.1 2018-12-21 [2] CRAN (R 3.6.1)
- REDCapR * 0.10.2.9005 2020-02-18 [1] local
- remotes 2.1.1 2020-02-15 [2] CRAN (R 3.6.2)
- rlang 0.4.4 2020-01-28 [2] CRAN (R 3.6.2)
+ REDCapR * 0.10.2.9006 2020-04-19 [1] local
+ rlang 0.4.5 2020-03-01 [2] CRAN (R 3.6.2)
rmarkdown 2.1 2020-01-20 [2] CRAN (R 3.6.2)
rprojroot 1.3-2 2018-01-03 [2] CRAN (R 3.6.1)
rstudioapi 0.11 2020-02-07 [2] CRAN (R 3.6.2)
rvest 0.3.5 2019-11-08 [2] CRAN (R 3.6.1)
scales 1.1.0 2019-11-18 [2] CRAN (R 3.6.1)
sessioninfo 1.1.1 2018-11-05 [2] CRAN (R 3.6.1)
- stringi 1.4.5 2020-01-11 [2] CRAN (R 3.6.1)
+ stringi 1.4.6 2020-02-17 [2] CRAN (R 3.6.2)
stringr 1.4.0 2019-02-10 [2] CRAN (R 3.6.1)
- testthat 2.3.1 2019-12-01 [2] CRAN (R 3.6.1)
- tibble 2.1.3 2019-06-06 [2] CRAN (R 3.6.1)
+ tibble 3.0.0 2020-03-30 [2] CRAN (R 3.6.3)
tidyselect 1.0.0 2020-01-27 [2] CRAN (R 3.6.2)
- usethis 1.5.1 2019-07-04 [2] CRAN (R 3.6.1)
- vctrs 0.2.2 2020-01-24 [2] CRAN (R 3.6.2)
+ vctrs 0.2.4 2020-03-10 [2] CRAN (R 3.6.3)
viridisLite 0.3.0 2018-02-01 [2] CRAN (R 3.6.1)
webshot 0.5.2 2019-11-22 [2] CRAN (R 3.6.1)
withr 2.1.2 2018-03-15 [2] CRAN (R 3.6.1)
xfun 0.12 2020-01-13 [2] CRAN (R 3.6.1)
- xml2 1.2.2 2019-08-09 [2] CRAN (R 3.6.1)
+ xml2 1.3.0 2020-04-01 [2] CRAN (R 3.6.3)
yaml 2.2.1 2020-02-01 [2] CRAN (R 3.6.2)
-[1] /tmp/RtmpQwpj1Q/temp_libpath20fe13c92d77
+[1] /tmp/Rtmp5avAp4/temp_libpath4e6a183ad817
[2] /home/wibeasley/R/x86_64-pc-linux-gnu-library/3.6
[3] /usr/local/lib/R/site-library
[4] /usr/lib/R/site-library
[5] /usr/lib/R/library
-Report rendered by wibeasley at 2020-02-18, 10:35 -0600 in 15 seconds.
+Report rendered by wibeasley at 2020-04-19, 13:31 -0500 in 15 seconds.
vignettes/SecurityDatabase.Rmd
SecurityDatabase.Rmd
auxiliary_security
here).rm(list=ls(all=TRUE)) #Clear the memory for any variables set from any previous runs.
-
-# ---- load-sources ------------------------------------------------------------
-
-# ---- load-packages -----------------------------------------------------------
-if( !require(OuhscMunge) )
- stop('The `OuhscMunge` package needs to be installed with `devtools::install_github("OuhscBbmc/OuhscMunge")`.')
-
-testit::assert(
- "The `OuhscMunge` package should meet a minimal version.",
- compareVersion( as.character(packageVersion("OuhscMunge")), "0.1.9.9009") >= 0L
-)
-
-library(magrittr)
-requireNamespace("DBI")
-requireNamespace("odbc")
-requireNamespace("dplyr")
-requireNamespace("readr")
-requireNamespace("tibble")
-requireNamespace("testit")
-requireNamespace("checkmate")
-requireNamespace("OuhscMunge") # devtools::install_github("OuhscBbmc/OuhscMunge")
-
-
-# ---- declare-globals ---------------------------------------------------------
-# This file assume your campus has two REDCap instances.
-# Modify each (a) database name, (b) REDCap URL, and (c) DSN name.
-
-name_production <- "production"
-name_dev <- "dev"
-
-uri_production <- "https://redcap-production.ouhsc.edu/redcap/api/",
-uri_dev <- "https://redcap-dev.ouhsc.edu/redcap/api/"
-
-dsn_production <- "redcap-production"
-dsn_dev <- "redcap-dev"
-dsn_source <- "auxiliary_security" # The DSN of the token server.
-
-# The Activity Directory name that should precede each username.
-# This should correspond with the result of SQL Server's `SYSTEM_USER` function
-# (https://msdn.microsoft.com/en-us/library/ms179930.aspx)
-ldap_prefix <- "OUHSC\\"
-
-####
-# Nothing below this line should need to change, assuming:
-# 1. the vignette was followed exactly (https://ouhscbbmc.github.io/REDCapR/articles/SecurityDatabase.html),
-# 2. your campus has exactly two REDCap instances.
-
-# SQL sent to the MySQL database underneath each REDCap instance.
-sql <- "
- SELECT username, project_id, api_token
- FROM redcap_user_rights
- WHERE api_token IS NOT NULL
-"
-
-# Update this ad-hoc CSV. Each row should represent one REDCap instance.
-ds_url <- tibble::tribble(
- ~instance , ~redcap_uri,
- name_production , uri_production,
- name_dev , uri_dev
-)
-
-# Remove variables that aren't used below.
-rm(uri_production, uri_dev)
-
-
-# ---- load-data ---------------------------------------------------------------
-
-# Load the credentials from the first/production REDCap instance.
-cnn_production <- DBI::dbConnect(odbc::odbc(), dsn=dsn_production)
-ds_production <- DBI::dbGetQuery(cnn_production, sql)
-DBI::dbDisconnect(cnn_production); rm(cnn_production, dsn_production)
-
-# Load the credentials from the second/dev REDCap instance.
-cnn_dev <- DBI::dbConnect(odbc::odbc(), dsn=dsn_dev)
-ds_dev <- DBI::dbGetQuery(cnn_dev, sql)
-DBI::dbDisconnect(cnn_dev); rm(cnn_dev, dsn_dev)
-
-rm(sql)
-
-# Assert these are valid datasets and contain at least 5 rows.
-# Adjust '5' to smaller value if necessary. It's just to catch blatant retrieval problems.
-checkmate::assert_data_frame(ds_production, min.rows=5)
-checkmate::assert_data_frame(ds_dev , min.rows=5)
-
-
-# ---- tweak-data --------------------------------------------------------------
-
-# Label each instance, so they're distinguishable later.
-ds_production$instance <- name_production
-ds_dev$instance <- name_dev
-
-# Stack the token collection from each instance. Then prefix the username and include the URL of each instance.
-ds <-
- ds_production %>%
- dplyr::union(ds_dev) %>% # Remove union if the dev instance isn't included.
- tibble::as_tibble() %>%
- dplyr::select(
- username = username,
- project_id = project_id,
- instance = instance,
- token = api_token
- ) %>%
- dplyr::mutate(
- username = paste0(ldap_prefix, username), # Qualify for the Active Directory.
- ) %>%
- dplyr::left_join( ds_url, by="instance") %>% # Include the instance URL.
- dplyr::arrange(instance, project_id, username) %>%
- tibble::rowid_to_column("id") # For the sake of a clustered primary key.
-
-rm(ds_production, ds_dev, ds_url)
-rm(name_production, name_dev)
-rm(ldap_prefix)
-
-
-# ---- verify-values -----------------------------------------------------------
-
-# Assert that the dataset is well-behaved.
-# OuhscMunge::verify_value_headstart(ds)
-checkmate::assert_integer( ds$id , any.missing=FALSE, lower=1, upper=.Machine$integer.max, unique=TRUE)
-checkmate::assert_character(ds$username , any.missing=FALSE, pattern="^.{1,255}$" )
-checkmate::assert_integer( ds$project_id , any.missing=FALSE, lower=1, upper=.Machine$integer.max )
-checkmate::assert_character(ds$token , any.missing=FALSE, pattern="^[A-Z0-9]{32}$" , unique=TRUE)
-checkmate::assert_character(ds$instance , any.missing=FALSE, pattern="^.{1,255}$" )
-checkmate::assert_character(ds$redcap_uri , any.missing=FALSE, pattern="^.{1,255}$" )
-
-testit::assert(
- "The `username` x `project_id` x `instance` must be unique.",
- sum(duplicated(paste0(ds$username, "-", ds$project_id, "-", ds$instance))) == 0L
-)
-
-testit::assert("At least 10 tokens should be ready to write." , 10L <= nrow(ds))
-
-
-# ---- specify-columns-to-upload -----------------------------------------------
-
-# Dictate the exact columns and order that will be uploaded.
-columns_to_write <- c("id", "username", "project_id", "instance", "token", "redcap_uri")
-ds_slim <- ds[, columns_to_write]
-rm(columns_to_write)
-
-
-# ---- upload-to-db ------------------------------------------------------------------
-
-OuhscMunge::upload_sqls_odbc(
- d = ds_slim,
- schema_name = "redcap_private",
- table_name = "tbl_credential",
- dsn_name = dsn_source,
- create_table = FALSE,
- clear_table = TRUE,
- transaction = TRUE,
- verbose = TRUE
-)
-# Uploading 252 tokens takes 0.004 minutes.
rm(list=ls(all=TRUE)) #Clear the memory for any variables set from any previous runs. + +# ---- load-sources ------------------------------------------------------------ + +# ---- load-packages ----------------------------------------------------------- +if (!require(OuhscMunge)) + stop('The `OuhscMunge` package needs to be installed with `remotes::install_github("OuhscBbmc/OuhscMunge")`.') + +testit::assert( + "The `OuhscMunge` package should meet a minimal version.", + compareVersion( as.character(packageVersion("OuhscMunge")), "0.1.9.9009") >= 0L +) + +library(magrittr) +requireNamespace("DBI") +requireNamespace("odbc") +requireNamespace("dplyr") +requireNamespace("readr") +requireNamespace("tibble") +requireNamespace("testit") +requireNamespace("checkmate") +requireNamespace("OuhscMunge") # remotes::install_github("OuhscBbmc/OuhscMunge") + + +# ---- declare-globals --------------------------------------------------------- +# This file assume your campus has two REDCap instances. +# Modify each (a) database name, (b) REDCap URL, and (c) DSN name. + +name_production % + dplyr::union(ds_dev) %>% # Remove union if the dev instance isn't included. + tibble::as_tibble() %>% + dplyr::select( + username = username, + project_id = project_id, + instance = instance, + token = api_token + ) %>% + dplyr::mutate( + username = paste0(ldap_prefix, username), # Qualify for the Active Directory. + ) %>% + dplyr::left_join( ds_url, by="instance") %>% # Include the instance URL. + dplyr::arrange(instance, project_id, username) %>% + tibble::rowid_to_column("id") # For the sake of a clustered primary key. + +rm(ds_production, ds_dev, ds_url) +rm(name_production, name_dev) +rm(ldap_prefix) + + +# ---- verify-values ----------------------------------------------------------- + +# Assert that the dataset is well-behaved. +# OuhscMunge::verify_value_headstart(ds) +checkmate::assert_integer( ds$id , any.missing=FALSE, lower=1, upper=.Machine$integer.max, unique=TRUE) +checkmate::assert_character(ds$username , any.missing=FALSE, pattern="^.{1,255}$" ) +checkmate::assert_integer( ds$project_id , any.missing=FALSE, lower=1, upper=.Machine$integer.max ) +checkmate::assert_character(ds$token , any.missing=FALSE, pattern="^[A-Z0-9]{32}$" , unique=TRUE) +checkmate::assert_character(ds$instance , any.missing=FALSE, pattern="^.{1,255}$" ) +checkmate::assert_character(ds$redcap_uri , any.missing=FALSE, pattern="^.{1,255}$" ) + +testit::assert( + "The `username` x `project_id` x `instance` must be unique.", + sum(duplicated(paste0(ds$username, "-", ds$project_id, "-", ds$instance))) == 0L +) + +testit::assert("At least 10 tokens should be ready to write." , 10L <= nrow(ds)) + + +# ---- specify-columns-to-upload ----------------------------------------------- + +# Dictate the exact columns and order that will be uploaded. +columns_to_write
vignettes/TroubleshootingApiCalls.Rmd
TroubleshootingApiCalls.Rmd
There are several ways to call REDCap’s API from R. The packages redcapAPI and REDCapR both rely on the httr package, which calls the curl package, which calls cURL.
Is httr installed on the user’s local machine? If so, running library(httr)
should not produce any error messages if you’re starting with a fresh session of R:
library(httr)
Is httr installed on the user’s local machine? If so, running library(httr)
should not produce any error messages if you’re starting with a fresh session of R:
library(httr)
Do you have the most recent version of httr? There are several ways to do this, but the easiest is probably to run update.packages(ask = FALSE, repos = "https://cran.rstudio.com")
. The optional argument ask
prevents the user from needing to respond ‘Y’ to each outdated package.
Can you query a test project using httr? Both the redcapAPI and REDCapR packages employ something similar to the following function in httr. If you’re curious, here is the relevant source code for redcapAPI and REDCapR.
If this check fails, consider attempting again with the url and token used above in the Postman example.
-redcap_uri <- "https://bbmc.ouhsc.edu/redcap/api/"
-token <- "9A81268476645C4E5F03428B8AC3AA7B"
-
-post_body <- list(
- token = token,
- content = 'record',
- format = 'csv',
- type = 'flat'
-)
-
-raw_text <- httr::POST(
- url = redcap_uri,
- body = post_body,
- httr::verbose() # Remove this line to suppress the console updates.
-)
-
-raw_text
redcap_uri <- "https://bbmc.ouhsc.edu/redcap/api/" +token <- "9A81268476645C4E5F03428B8AC3AA7B" + +post_body <- list( + token = token, + content = 'record', + format = 'csv', + type = 'flat' +) + +raw_text <- httr::POST( + url = redcap_uri, + body = post_body, + httr::verbose() # Remove this line to suppress the console updates. +) + +raw_text
Alternatively, you can try using the RCurl package, which has been mostly replaced by httr in packages developed since 2014.
-raw_text <- RCurl::postForm(
- uri = redcap_uri
- , token = token
- , content = 'record'
- , format = 'csv'
- , type = 'flat'
-)
raw_text <- RCurl::postForm( + uri = redcap_uri + , token = token + , content = 'record' + , format = 'csv' + , type = 'flat' +)
Can you query a subset of your project using httr? This step is like the previous one, but with two differences. First, it’s using your REDCap project (instead of the test project). Second, it pulls fewer records, and a smaller collection of fields. Subsetting can help troubleshoot by avoiding (and thus identifying) cells with problematic values.
Notice this call now passes values to the records
and fields
parameters. Also notice each value is a single long string (rather a vector of shorter strings, which is more natural to most R users).
redcap_uri <- "https://the.urlofyourinsitution.edu/api/"
-token <- "your-secret-token"
-
-records_collapsed <- "1,2,3" # Assumes dataset contains ID values of 1-3.
-fields_collapsed <- "record_id,name_first,name_last" # Assumes dataset contains these variables.
-
-post_body <- list(
- token = token,
- content = 'record',
- format = 'csv',
- type = 'flat',
- records = records_collapsed,
- fields = fields_collapsed
-)
-
-raw_text <- httr::POST(
- url = redcap_uri,
- body = post_body,
- httr::verbose() # Remove this line to suppress the console updates.
-)
-
-raw_text
redcap_uri <- "https://the.urlofyourinsitution.edu/api/" +token <- "your-secret-token" + +records_collapsed <- "1,2,3" # Assumes dataset contains ID values of 1-3. +fields_collapsed <- "record_id,name_first,name_last" # Assumes dataset contains these variables. + +post_body <- list( + token = token, + content = 'record', + format = 'csv', + type = 'flat', + records = records_collapsed, + fields = fields_collapsed +) + +raw_text <- httr::POST( + url = redcap_uri, + body = post_body, + httr::verbose() # Remove this line to suppress the console updates. +) + +raw_text
Can you query an entire project using httr? There are two advantages of trying a subset of the data. First, small datasets avoid the time-out errors that plague large datasets. Second, it may avoid problematic values being passed through the pipeline. If the current check fails but the previous check succeeds, then experiment with different expanses of records and fields. This should help determine which values are causing the problems, or if there’s simply too much data being pulled in one pass.
If the desired dataset is too large, consider if you can prune unnecessary records or fields. If not, one solution is to pull smaller, multiple batches using the API, then reassemble them. The redcap_read()
function in REDCapR does this automatically, and allows the user to specify a batch_size
.
redcap_uri <- "https://the.urlofyourinsitution.edu/api/"
-token <- "your-secret-token"
-
-records_collapsed <- NULL
-fields_collapsed <- NULL
-
-post_body <- list(
- token = token,
- content = 'record',
- format = 'csv',
- type = 'flat',
- records = records_collapsed,
- fields = fields_collapsed
-)
-
-raw_text <- httr::POST(
- url = redcap_uri,
- body = post_body,
- httr::verbose() # Remove this line to suppress the console updates.
-)
-
-raw_text
redcap_uri <- "https://the.urlofyourinsitution.edu/api/" +token <- "your-secret-token" + +records_collapsed <- NULL +fields_collapsed <- NULL + +post_body <- list( + token = token, + content = 'record', + format = 'csv', + type = 'flat', + records = records_collapsed, + fields = fields_collapsed +) + +raw_text <- httr::POST( + url = redcap_uri, + body = post_body, + httr::verbose() # Remove this line to suppress the console updates. +) + +raw_text
If all these checks pass, proceed to the next section. If not, start by consulting your REDCap administrator.
@@ -316,81 +298,81 @@Is the latest version of REDCapR installed on your machine? Currently the easiest way to install REDCapR is with the remotes package. The following code installs remotes, then installs REDCapR. The CRAN version of REDCapR is updated only a few times a year, while the code below will download the latest stable version.
-install.packages("remotes", repos = "https://cran.rstudio.com")
-remotes::install_github(repo = "OuhscBbmc/REDCapR")
install.packages("remotes", repos = "https://cran.rstudio.com") +remotes::install_github(repo = "OuhscBbmc/REDCapR")
Does REDCapR load successfully on your machine? If so, running library(REDCapR)
should produce the following output if you’re starting with a fresh session of R:
library(REDCapR)
-# Loading required package: REDCapR
Does REDCapR load successfully on your machine? If so, running library(REDCapR)
should produce the following output if you’re starting with a fresh session of R:
library(REDCapR) +# Loading required package: REDCapR
Can you export their data dictionary? Sometimes the problem exists within the metadata/dictionary, instead of the actual data values. Verify the structure and content of this specific project is interpretable by your local environment.
-library(REDCapR) # Load the package into the current R session, if you haven't already.
-redcap_uri <- "https://the.urlofyourinsitution.edu/api/"
-token <- "your-secret-token"
-redcap_metadata_read(redcap_uri = uri, token = token)
If this fails, see “Problems in the project’s metadata/dictionary.” under Gotchas below.
+library(REDCapR) # Load the package into the current R session, if you haven't already. +redcap_uri <- "https://the.urlofyourinsitution.edu/api/" +token <- "your-secret-token" +redcap_metadata_read(redcap_uri = uri, token = token)
If this fails, see “Problems in the project’s metadata/dictionary” under Common Gotchas above. A problematic data dictionary may produce the error Error in inherits(ds, "data.frame") : object 'ds' not found
when calling REDCapR::redcap_metadata_read()
.
Can you export from an example project? This is the same fake data hosted by the OUHSC BBMC as in the previous section.
-library(REDCapR) # Load the package into the current R session.
-uri <- "https://bbmc.ouhsc.edu/redcap/api/"
-token <- "9A81268476645C4E5F03428B8AC3AA7B"
-redcap_read(redcap_uri = uri, token = token)$data
library(REDCapR) # Load the package into the current R session. +uri <- "https://bbmc.ouhsc.edu/redcap/api/" +token <- "9A81268476645C4E5F03428B8AC3AA7B" +redcap_read(redcap_uri = uri, token = token)$data
The previous code should produce similar output. Notice there are five rows and the columns will wrap around if your console window is too narrow.
-5 records and 1 columns were read from REDCap in 0.41 seconds.
-Starting to read 5 records at 2014-06-27 17:19:49
-Reading batch 1 of 1, with ids 1 through 5.
-5 records and 16 columns were read from REDCap in 0.42 seconds.
-
- record_id name_first name_last address telephone email
-1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232 (432) 456-4848 nutty@mouse.com
-2 2 Tumtum Nutmouse 14 Rose Cottage Blvd.\nKenning UK 34243 (234) 234-2343 tummy@mouse.comm
-3 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402 (433) 435-9865 mw@mwood.net
-4 4 Trudy DAG 342 Elm\nDuncanville TX, 75116 (987) 654-3210 peroxide@blonde.com
-5 5 John Lee Walker Hotel Suite\nNew Orleans LA, 70115 (333) 333-4444 left@hippocket.com
-
- dob age ethnicity race sex height weight bmi
-1 2003-08-30 10 1 2 0 5.00 1 400.0
-2 2003-03-10 10 1 6 1 6.00 1 277.8
-3 1934-04-09 79 0 4 1 180.00 80 24.7
-4 1952-11-02 61 1 4 0 165.00 54 19.8
-5 1955-04-15 58 1 4 1 193.04 104 27.9
-
- comments
-1 Character in a book, with some guessing
-2 A mouse character from a good book
-3 completely made up
-4 This record doesn't have a DAG assigned\n\nSo call up Trudy on the telephone\nSend her a letter in the mail
-5 Had a hand for trouble and a eye for cash\n\nHe had a gold watch chain and a black mustache
-
- demographics_complete
-1 2
-2 2
-3 2
-4 2
-5 2
5 records and 1 columns were read from REDCap in 0.41 seconds. +Starting to read 5 records at 2014-06-27 17:19:49 +Reading batch 1 of 1, with ids 1 through 5. +5 records and 16 columns were read from REDCap in 0.42 seconds. + + record_id name_first name_last address telephone email +1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232 (432) 456-4848 nutty@mouse.com +2 2 Tumtum Nutmouse 14 Rose Cottage Blvd.\nKenning UK 34243 (234) 234-2343 tummy@mouse.comm +3 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402 (433) 435-9865 mw@mwood.net +4 4 Trudy DAG 342 Elm\nDuncanville TX, 75116 (987) 654-3210 peroxide@blonde.com +5 5 John Lee Walker Hotel Suite\nNew Orleans LA, 70115 (333) 333-4444 left@hippocket.com + + dob age ethnicity race sex height weight bmi +1 2003-08-30 10 1 2 0 5.00 1 400.0 +2 2003-03-10 10 1 6 1 6.00 1 277.8 +3 1934-04-09 79 0 4 1 180.00 80 24.7 +4 1952-11-02 61 1 4 0 165.00 54 19.8 +5 1955-04-15 58 1 4 1 193.04 104 27.9 + + comments +1 Character in a book, with some guessing +2 A mouse character from a good book +3 completely made up +4 This record doesn't have a DAG assigned\n\nSo call up Trudy on the telephone\nSend her a letter in the mail +5 Had a hand for trouble and a eye for cash\n\nHe had a gold watch chain and a black mustache + + demographics_complete +1 2 +2 2 +3 2 +4 2 +5 2
Can you export from your own project? The code is similar to the previous check, but the uri
and token
values will need to be modified.
library(REDCapR) # Load the package into the current R session, if you haven't already.
-redcap_uri <- "https://the.urlofyourinsitution.edu/api/"
-token <- "your-secret-token"
-redcap_read(redcap_uri = uri, token = token)$data
library(REDCapR) # Load the package into the current R session, if you haven't already. +redcap_uri <- "https://the.urlofyourinsitution.edu/api/" +token <- "your-secret-token" +redcap_read(redcap_uri = uri, token = token)$data
Alternatively, a redcap_project
object can be declared initially, which makes subsequent calls cleaner when the token and url are required only the when the object is declared.
library(REDCapR) # Load the package into the current R session, if you haven't already.
-uri <- "https://bbmc.ouhsc.edu/redcap/api/"
-token <- "9A81268476645C4E5F03428B8AC3AA7B"
-project <- redcap_project$new(redcap_uri = uri, token = token)
-
-ds_three_columns <- project$read(fields = c("record_id", "sex", "age"))$data
-
-ids_of_males <- ds_three_columns$record_id[ds_three_columns$sex == 1]
-ids_of_minors <- ds_three_columns$record_id[ds_three_columns$age < 18]
-
-ds_males <- project$read(records = ids_of_males, batch_size = 2)$data
-ds_minors <- project$read(records = ids_of_minors)$data
library(REDCapR) # Load the package into the current R session, if you haven't already. +uri <- "https://bbmc.ouhsc.edu/redcap/api/" +token <- "9A81268476645C4E5F03428B8AC3AA7B" +project <- redcap_project$new(redcap_uri = uri, token = token) + +ds_three_columns <- project$read(fields = c("record_id", "sex", "age"))$data + +ids_of_males <- ds_three_columns$record_id[ds_three_columns$sex == 1] +ids_of_minors <- ds_three_columns$record_id[ds_three_columns$age < 18] + +ds_males <- project$read(records = ids_of_males, batch_size = 2)$data +ds_minors <- project$read(records = ids_of_minors)$data
Is the export operation still unsuccessful using REDCapR? If so the “Can the user query a entire REDCap project using httr?” check succeeded, but the REDCapR checks did not, consider posting a new GitHub issue to the package developers.
Is redcapAPI installed on your machine? Currently, the easiest way to install redcapAPI
is from CRAN.
install.packages("redcapAPI")
install.packages("redcapAPI")
Developmental versions may be available on GitHub.
-install.packages("remotes", repos = "http://cran.rstudio.com")
-remotes::install_github(repo = "nutterb/redcapAPI")
install.packages("remotes", repos = "http://cran.rstudio.com") +remotes::install_github(repo = "nutterb/redcapAPI")
Does redcapAPI load successfully on your machine? If so, running library(redcapAPI)
should produce the following output if you’re starting with a fresh session of R:
library(redcapAPI)
-# Loading required package: redcapAPI
Does redcapAPI load successfully on your machine? If so, running library(redcapAPI)
should produce the following output if you’re starting with a fresh session of R:
library(redcapAPI) +# Loading required package: redcapAPI
Can you export their data dictionary? Sometimes the problem exists within the metadata/dictionary, instead of the actual data values. Verify the structure and content of this specific project is interpretable by your local environment.
-library(redcapAPI) # Load the package into the current R session, if you haven't already.
-redcap_uri <- "https://the.urlofyourinsitution.edu/api/"
-token <- "your-secret-token"
-exportMetaData(rcon)
If this fails, see “Problems in the project’s metadata/dictionary.” under Gotchas below.
+library(redcapAPI) # Load the package into the current R session, if you haven't already. +redcap_uri <- "https://the.urlofyourinsitution.edu/api/" +token <- "your-secret-token" +exportMetaData(rcon)
If this fails, see “Problems in the project’s metadata/dictionary.” under Gotchas above
Can you export from an example project? This is the same fake data hosted by the OUHSC BBMC as in the previous section.
-library(redcapAPI) # Load the package into the current R session.
-rcon <- redcapConnection(
- url = "https://bbmc.ouhsc.edu/redcap/api/",
- token = "9A81268476645C4E5F03428B8AC3AA7B"
-)
-exportRecords(rcon)
library(redcapAPI) # Load the package into the current R session. +rcon <- redcapConnection( + url = "https://bbmc.ouhsc.edu/redcap/api/", + token = "9A81268476645C4E5F03428B8AC3AA7B" +) +exportRecords(rcon)
The previous code should produce similar output. Notice there are five rows and the columns will wrap around if your console window is too narrow.
-record_id name_first name_last address telephone email
-1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232 (432) 456-4848 nutty@mouse.com
-2 2 Tumtum Nutmouse 14 Rose Cottage Blvd.\nKenning UK 34243 (234) 234-2343 tummy@mouse.comm
-3 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402 (433) 435-9865 mw@mwood.net
-4 4 Trudy DAG 342 Elm\nDuncanville TX, 75116 (987) 654-3210 peroxide@blonde.com
-5 5 John Lee Walker Hotel Suite\nNew Orleans LA, 70115 (333) 333-4444 left@hippocket.com
-
- dob age ethnicity race sex height weight bmi
-1 2003-08-30 10 1 2 0 5.00 1 400.0
-2 2003-03-10 10 1 6 1 6.00 1 277.8
-3 1934-04-09 79 0 4 1 180.00 80 24.7
-4 1952-11-02 61 1 4 0 165.00 54 19.8
-5 1955-04-15 58 1 4 1 193.04 104 27.9
-
- comments
-1 Character in a book, with some guessing
-2 A mouse character from a good book
-3 completely made up
-4 This record doesn't have a DAG assigned\n\nSo call up Trudy on the telephone\nSend her a letter in the mail
-5 Had a hand for trouble and a eye for cash\n\nHe had a gold watch chain and a black mustache
-
-demographics_complete
-1 2
-2 2
-3 2
-4 2
-5 2
record_id name_first name_last address telephone email +1 1 Nutmeg Nutmouse 14 Rose Cottage St.\nKenning UK, 323232 (432) 456-4848 nutty@mouse.com +2 2 Tumtum Nutmouse 14 Rose Cottage Blvd.\nKenning UK 34243 (234) 234-2343 tummy@mouse.comm +3 3 Marcus Wood 243 Hill St.\nGuthrie OK 73402 (433) 435-9865 mw@mwood.net +4 4 Trudy DAG 342 Elm\nDuncanville TX, 75116 (987) 654-3210 peroxide@blonde.com +5 5 John Lee Walker Hotel Suite\nNew Orleans LA, 70115 (333) 333-4444 left@hippocket.com + + dob age ethnicity race sex height weight bmi +1 2003-08-30 10 1 2 0 5.00 1 400.0 +2 2003-03-10 10 1 6 1 6.00 1 277.8 +3 1934-04-09 79 0 4 1 180.00 80 24.7 +4 1952-11-02 61 1 4 0 165.00 54 19.8 +5 1955-04-15 58 1 4 1 193.04 104 27.9 + + comments +1 Character in a book, with some guessing +2 A mouse character from a good book +3 completely made up +4 This record doesn't have a DAG assigned\n\nSo call up Trudy on the telephone\nSend her a letter in the mail +5 Had a hand for trouble and a eye for cash\n\nHe had a gold watch chain and a black mustache + +demographics_complete +1 2 +2 2 +3 2 +4 2 +5 2
Can you export your own project? The code is similar to the previous check, but the uri
and token
values will need to be modified.
library(redcapAPI) # Load the package into the current R session, if you haven't already.
-rcon <- redcapConnection(
- url = "https://the.urlofyourinsitution.edu/api/", # Adapt this to your server.
- token = "your-secret-token" # Adapt this to your user's token.
-)
-exportRecords(rcon)
library(redcapAPI) # Load the package into the current R session, if you haven't already. +rcon <- redcapConnection( + url = "https://the.urlofyourinsitution.edu/api/", # Adapt this to your server. + token = "your-secret-token" # Adapt this to your user's token. +) +exportRecords(rcon)
Is the export operation still unsuccessful using redcapAPI? If so the “Can the user query a entire REDCap project using httr?” check succeeded, but the redcapAPI checks did not, consider posting a new GitHub issue to the package developers.
vignettes/advanced-redcapr-operations.Rmd
advanced-redcapr-operations.Rmd
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.
Other than PHI-free demos, we strongly suggest storing tokens securely and avoiding hard-coding them like below. Our recommendation is to store tokens in a database. If that is not feasible for your institution, consider storing them in a secured csv and retrieving with REDCapR::retrieve_credential_local()
.
library(REDCapR) #Load the package into the current R session.
-uri <- "https://bbmc.ouhsc.edu/redcap/api/"
-token_simple <- "9A81268476645C4E5F03428B8AC3AA7B"
-token_longitudinal <- "0434F0E9CF53ED0587847AB6E51DE762"
library(REDCapR) #Load the package into the current R session. +uri <- "https://bbmc.ouhsc.edu/redcap/api/" +token_simple <- "9A81268476645C4E5F03428B8AC3AA7B" +token_longitudinal <- "0434F0E9CF53ED0587847AB6E51DE762"
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.6 seconds. The http status code was 200.
-ds_long %>%
- dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4)
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.
+ds_long %>% + dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4)
#> 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
@@ -166,44 +148,44 @@
#> 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::pivot_wider(
- id_cols = study_id,
- names_from = redcap_event_name,
- values_from = pmq1
- )
- # For old versions of tidyr that predate `pivot_wider()`:
- # tidyr::spread(key=redcap_event_name, value=pmq1)
-ds_wide
ds_wide <- + ds_long %>% + dplyr::select(study_id, redcap_event_name, pmq1) %>% + dplyr::filter(redcap_event_name %in% events_to_retain) %>% + tidyr::pivot_wider( + id_cols = study_id, + names_from = redcap_event_name, + values_from = pmq1 + ) + # For old versions of tidyr that predate `pivot_wider()`: + # tidyr::spread(key=redcap_event_name, value=pmq1) +ds_wide
#> # A tibble: 2 x 5
#> study_id dose_1_arm_1 visit_1_arm_1 dose_2_arm_1 visit_2_arm_1
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 100 2 1 3 0
#> 2 220 0 0 1 3
In some scenarios, multiple variables (e.g., pmq1
- pmq4
) can be widened in a single tidyr::pivot_wider()
operation. This example contains the additional wrinkle that the REDCap event names “first_dose” and “first_visit” are renamed “dose_1” and “visit_1”, which will help all the values be dose and visit values be proper numbers.
pattern <- "^(\\w+?)_arm_(\\d)$"
-ds_wide <-
- ds_long %>%
- dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4) %>%
- dplyr::mutate(
- event = sub(pattern, "\\1", redcap_event_name),
- event = dplyr::recode(event, "first_dose"="dose_1", "first_visit"="visit_1"),
- arm = as.integer(sub(pattern, "\\2", redcap_event_name))
- ) %>%
- dplyr::select(study_id, event, arm, pmq1, pmq2, pmq3, pmq4) %>%
- dplyr::filter(!(event %in% c(
- "enrollment", "final_visit", "deadline_to_return", "deadline_to_opt_ou")
- )) %>%
- tidyr::pivot_wider(
- id_cols = c(study_id, arm),
- names_from = event,
- values_from = c(pmq1, pmq2, pmq3, pmq4)
- )
-
-ds_wide
pattern <- "^(\\w+?)_arm_(\\d)$" +ds_wide <- + ds_long %>% + dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4) %>% + dplyr::mutate( + event = sub(pattern, "\\1", redcap_event_name), + event = dplyr::recode(event, "first_dose"="dose_1", "first_visit"="visit_1"), + arm = as.integer(sub(pattern, "\\2", redcap_event_name)) + ) %>% + dplyr::select(study_id, event, arm, pmq1, pmq2, pmq3, pmq4) %>% + dplyr::filter(!(event %in% c( + "enrollment", "final_visit", "deadline_to_return", "deadline_to_opt_ou") + )) %>% + tidyr::pivot_wider( + id_cols = c(study_id, arm), + names_from = event, + values_from = c(pmq1, pmq2, pmq3, pmq4) + ) + +ds_wide
#> # A tibble: 3 x 18
#> study_id arm pmq1_dose_1 pmq1_visit_1 pmq1_dose_2 pmq1_visit_2 pmq2_dose_1
#> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
@@ -215,33 +197,33 @@
#> # pmq3_dose_2 <dbl>, pmq3_visit_2 <dbl>, pmq4_dose_1 <dbl>,
#> # pmq4_visit_1 <dbl>, pmq4_dose_2 <dbl>, pmq4_visit_2 <dbl>
However, in other widening scenarios, it can be easier to go even longer/taller (e.g., ds_eav
) before reversing direction and going wide.
ds_eav <-
- ds_long %>%
- dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4) %>%
- dplyr::mutate(
- event = sub(pattern, "\\1", redcap_event_name),
- event = dplyr::recode(event, "first_dose"="dose_1", "first_visit"="visit_1"),
- arm = as.integer(sub(pattern, "\\2", redcap_event_name))
- ) %>%
- dplyr::select(study_id, event, arm, pmq1, pmq2, pmq3, pmq4) %>%
- tidyr::pivot_longer(
- cols = c(pmq1, pmq2, pmq3, pmq4),
- names_to = "key",
- values_to = "value"
- ) %>%
- # For old versions of tidyr that predate `pivot_wider()`:
- # 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:
- key = paste0(key, "_", event)
- ) %>%
- dplyr::select(-event)
-
-# Show the first 10 rows of the EAV table.
-ds_eav %>%
- head(10)
ds_eav <- + ds_long %>% + dplyr::select(study_id, redcap_event_name, pmq1, pmq2, pmq3, pmq4) %>% + dplyr::mutate( + event = sub(pattern, "\\1", redcap_event_name), + event = dplyr::recode(event, "first_dose" = "dose_1", "first_visit" = "visit_1"), + arm = as.integer(sub(pattern, "\\2", redcap_event_name)) + ) %>% + dplyr::select(study_id, event, arm, pmq1, pmq2, pmq3, pmq4) %>% + tidyr::pivot_longer( + cols = c(pmq1, pmq2, pmq3, pmq4), + names_to = "key", + values_to = "value" + ) %>% + # For old versions of tidyr that predate `pivot_wider()`: + # 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: + key = paste0(key, "_", event) + ) %>% + dplyr::select(-event) + +# Show the first 10 rows of the EAV table. +ds_eav %>% + head(10)
#> # A tibble: 10 x 4
#> study_id arm key value
#> <dbl> <int> <chr> <dbl>
@@ -255,17 +237,17 @@
#> 8 100 1 pmq4_visit_1 0
#> 9 100 1 pmq1_dose_2 3
#> 10 100 1 pmq2_dose_2 1
-# Spread the EAV to wide.
-ds_wide_2 <-
- ds_eav %>%
- tidyr::pivot_wider(
- id_cols = c(study_id, arm),
- names_from = key,
- values_from = value
- )
- # For old versions of tidyr that predate `pivot_wider()`:
- # tidyr::spread(key=key, value=value)
-ds_wide_2
# Spread the EAV to wide. +ds_wide_2 <- + ds_eav %>% + tidyr::pivot_wider( + id_cols = c(study_id, arm), + names_from = key, + values_from = value + ) + # For old versions of tidyr that predate `pivot_wider()`: + # tidyr::spread(key=key, value=value) +ds_wide_2
#> # A tibble: 3 x 18
#> study_id arm pmq1_dose_1 pmq2_dose_1 pmq3_dose_1 pmq4_dose_1 pmq1_visit_1
#> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
@@ -278,35 +260,64 @@
#> # pmq2_visit_2 <dbl>, pmq3_visit_2 <dbl>, pmq4_visit_2 <dbl>
Lots of packages and documentation exist. Our current preference is the tidyverse approach to pivoting, but the data.table approach is worth considering if you’re comfortable with that package. This Stack Overflow post describes several ways. We recommend against the reshape and reshape2 packages, because their developers have replaced them with the tidyr functions described above.
If you require a feature that is not available from your instance’s API, first upgrade your institution’s REDcap instance and see if the feature has been added recently. Second, check if someone has released the desired API-like features as an REDCap External Module.
+Third, you may need to query the database underneath REDCap’s web server. The Transfer Credentials section of the Security Database Vignette provides a complete example of using R to query the MySQL database through odbc.
+We find it’s best to develop the query in MySQL Workbench, then copy the code to R (or alternatively, use OuhscMunge::execute_sql_file()
).
Here is an example that retrieves the first_submit_time
, which is helpful if you need a timestamp from surveys that were not marked as completed. Replace ‘444’ with your pid, and 1001 through 1003 with the desired events.
SELECT
+ p.participant_id as participant_survey_id
+ ,r.record as record_id
+ ,p.event_id
+ ,e.descrip as event_name
+ ,r.first_submit_time
+ ,r.completion_time
+
+ -- ,p.*
+ -- ,r.*
+FROM redcapv3.redcap_surveys_participants as p
+ left join redcapv3.redcap_surveys_response as r on p.participant_id = r.participant_id
+ left join redcapv3.redcap_events_metadata as e on p.event_id = e.event_id
+where
+ p.survey_id = 444
+ and
+ p.event_id in (
+ 1001, -- start of the year
+ 1002, -- mid term
+ 1003 -- end of year
+ )
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
-}
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.2 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
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.2 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.2 seconds. The http status code was 200.
If you require a feature that is not available from your instance’s API, first upgrade your institution’s REDcap instance and see if the feature has been added recently. Second, check if someone has released the desired API-like features as an REDCap External Module.
-Third, you may need to query the database underneath REDCap’s web server. The Transfer Credentials section of the Security Database Vignette provides a complete example of using R to query the MySQL database through odbc.
-We find it’s best to develop the query in MySQL Workbench, then copy the code to R (or alternatively, use OuhscMunge::execute_sql_file()
).
Here is an example that retrieves the first_submit_time
, which is helpful if you need a timestamp from surveys that were not marked as completed. Replace ‘444’ with your pid, and 1001 through 1003 with the desired events.
SELECT
- p.participant_id as participant_survey_id
- ,r.record as record_id
- ,p.event_id
- ,e.descrip as event_name
- ,r.first_submit_time
- ,r.completion_time
-
- -- ,p.*
- -- ,r.*
-FROM redcapv3.redcap_surveys_participants as p
- left join redcapv3.redcap_surveys_response as r on p.participant_id = r.participant_id
- left join redcapv3.redcap_events_metadata as e on p.event_id = e.event_id
-where
- p.survey_id = 444
- and
- p.event_id in (
- 1001, -- start of the year
- 1002, -- mid term
- 1003 -- end of year
- )
Report rendered by wibeasley at 2020-03-13, 20:40 -0500 in 4 seconds.
+Report rendered by wibeasley at 2020-04-19, 13:32 -0500 in 7 seconds.
These vignettes provide an introduction to REDCapR.
- +We’ve been using R with REDCap’s API since 2012 and have developed REDCapR
. Before encapsulating these functions in a package, we were replicating 50+ lines of code to contact REDCap and robustly transform the returned csv into an R data.frame
; it took twice that much to implement batching. All this can be done in one call to redcap_read()
:
ds <- redcap_read(redcap_uri=uri, token=token)$data
Weâve been using R with REDCapâs API since 2012 and have developed REDCapR
. Before encapsulating these functions in a package, we were replicating 50+ lines of code to contact REDCap and robustly transform the returned csv into an R data.frame
; it took twice that much to implement batching. All this can be done in one call to redcap_read()
:
ds <- redcap_read(redcap_uri=uri, token=token)$data
The redcap_read()
function also accepts values for subsetting/filtering the records and fields. Here are two examples; the first selects only a portion of the rows, while the second selects only a portion of the columns. Documentation for the additional 20+ functions are found at ouhscbbmc.github.io/REDCapR/reference.
# Return only records with IDs of 1 and 4
-desired_records <- c(1, 4)
-ds_some_rows <- redcap_read(
- redcap_uri = uri,
- token = token,
- records = desired_records
-)$data
-
-# Return only the fields record_id, name_first, and age
-desired_fields <- c("record_id", "name_first", "age")
-ds_some_fields <- redcap_read(
- redcap_uri = uri,
- token = token,
- fields = desired_fields
-)$data
The REDCapR
package includes the SSL certificate retrieved by httr::find_cert_bundle()
. Your REDCap server’s identity is always verified, unless the setting is overridden (alternative certificates can also be provided).
To keep our maintenance efforts manageable, the package implements only the REDCap API functions that have been requested. If there’s a feature that would help your projects, please tell us in a new issue in REDCapR’s GitHub repository. A troubleshooting document helps diagnose issues with the API.
+# Return only records with IDs of 1 and 4 +desired_records <- c(1, 4) +ds_some_rows <- redcap_read( + redcap_uri = uri, + token = token, + records = desired_records +)$data + +# Return only the fields record_id, name_first, and age +desired_fields <- c("record_id", "name_first", "age") +ds_some_fields <- redcap_read( + redcap_uri = uri, + token = token, + fields = desired_fields +)$data
The REDCapR
package includes the SSL certificate retrieved by httr::find_cert_bundle()
. Your REDCap serverâs identity is always verified, unless the setting is overridden (alternative certificates can also be provided).
To keep our maintenance efforts manageable, the package implements only the REDCap API functions that have been requested. If thereâs a feature that would help your projects, please tell us in a new issue in REDCapRâs GitHub repository. A troubleshooting document helps diagnose issues with the API.
The release version can be installed from CRAN.
-install.packages("REDCapR")
install.packages("REDCapR")
The development version can be installed from GitHub after installing the remotes
package.
install.packages("remotes") # Run this line if the 'remotes' package isn't installed already.
-remotes::install_github(repo="OuhscBbmc/REDCapR")
install.packages("remotes") # Run this line if the 'remotes' package isn't installed already. +remotes::install_github(repo="OuhscBbmc/REDCapR")
The ouhscbbmc.github.io/REDCapR site describes the package functions, and includes documents involving basic operations, advanced operations, token security, and troubleshooting.
Also checkout the other packages that exist for communicating with REDCap, which are listed in the REDCap Tools directory.
We encourage input and collaboration. If you’re familiar with GitHub and R packages, feel free to submit a pull request. If you’d like to report a bug or make a suggestion, please create a GitHub issue; issues are a usually a good place to ask public questions too. However, feel free to email Will (wibeasley@hotmail.com). Please note that this project is released with a Contributor Code of Conduct; by participating in this project you agree to abide by its terms. We have some starting material described in the ./documentation-for-developers/
directory.
We’d like to thank the following developers for their advice and code contributions: Benjamin Nutter, Rollie Parrish, Scott Burns, John Aponte, Andrew Peters, and Hao Zhu.
+We encourage input and collaboration. If youâre familiar with GitHub and R packages, feel free to submit a pull request. If youâd like to report a bug or make a suggestion, please create a GitHub issue; issues are a usually a good place to ask public questions too. However, feel free to email Will (wibeasley@hotmail.com). Please note that this project is released with a Contributor Code of Conduct; by participating in this project you agree to abide by its terms. We have some starting material described in the ./documentation-for-developers/
directory.
Weâd like to thank the following developers for their advice and code contributions: Benjamin Nutter, Rollie Parrish, Scott Burns, John Aponte, Andrew Peters, and Hao Zhu.
Much of this package has been developed to support the needs of the following projects. We appreciate the support. (So far) the primary developers of REDCapR are the external evaluators for Oklahoma’s MIECHV program. See the preliminary CQI reports (many of which use REDCapR) at http://ouhscbbmc.github.io/MReportingPublic/.
+Much of this package has been developed to support the needs of the following projects. We appreciate the support. (So far) the primary developers of REDCapR are the external evaluators for Oklahomaâs MIECHV program. See the preliminary CQI reports (many of which use REDCapR) at http://ouhscbbmc.github.io/MReportingPublic/.
kernel_api()
defaults to “text/csv” and UTF-8 encoding. Formerly, the function would decide on the content-type and encoding. More details are below in the ‘Stability Features’ subsection.
kernel_api()
defaults to âtext/csvâ and UTF-8 encoding. Formerly, the function would decide on the content-type and encoding. More details are below in the âStability Featuresâ subsection.
constant()
no longer accepts simplify
as an options. An integer vector is always returned. (#280)
It’s now possible to specify the exact col_types
(a readr::cols
object) that is passed to readr::read_csv()
inside redcap_read_oneshot()
. (#258)
reader::type_convert()
is used after all the batches are stacked on top of each other. This way, batches cannot have incompatible data types as they’re combined. (#257; thanks @isaactpetersen #245) Consequently, the guess_max
parameter in redcap_read()
no longer serves a purpose, and has been soft-deprecated. (#267)
redcap_metadata_write()
writes to the project’s metadata. (#274, @felixetorres)
Itâs now possible to specify the exact col_types
(a readr::cols
object) that is passed to readr::read_csv()
inside redcap_read_oneshot()
. (#258)
reader::type_convert()
is used after all the batches are stacked on top of each other. This way, batches cannot have incompatible data types as theyâre combined. (#257; thanks @isaactpetersen #245) Consequently, the guess_max
parameter in redcap_read()
no longer serves a purpose, and has been soft-deprecated. (#267)
redcap_metadata_write()
writes to the projectâs metadata. (#274, @felixetorres)
redcap_survey_link_export_oneshot()
retrieves the URL to a specific recordâs suvey (e.g., âhttps://bbmc.ouhsc.edu/redcap/surveys/?s=8KuzSLMHf6â) (#293)
httr::content()
(which is inside kernel_api()
) now processes the returned value as “text/csv”, by default. This should prevent strange characters from tricking the process as the internal variable raw_text
is being formed. See the [httr::content()](https://httr.r-lib.org/reference/content.html) documentation for a list of possible values for the
content_type` parameter. (Thanks to great debugging by @vortexing, #269)
Similarly, kernel_api()
now has an encoding
parameter, which defaults to “UTF-8”. (#270)
httr::content()
(which is inside kernel_api()
) now processes the returned value as âtext/csvâ, by default. This should prevent strange characters from tricking the process as the internal variable raw_text
is being formed. See the [httr::content()](https://httr.r-lib.org/reference/content.html) documentation for a list of possible values for the
content_type` parameter. (Thanks to great debugging by @vortexing #269, @sybandrew #272, & @begavett, #290)
Similarly, kernel_api()
now has an encoding
parameter, which defaults to âUTF-8â. (#270)
redcap_next_free_record_name()
: API call for ‘Generate Next Record Name’, which returns the next available record ID (Issue #237)redcap_next_free_record_name()
: API call for âGenerate Next Record Nameâ, which returns the next available record ID (Issue #237)
redcap_read()
and redcap_read_oneshot()
allow the user to specify if all variables should be returned with the character
data type. The default is to allow readr::read_csv()
to guess the data type. (#194)redcap_read()
, redcap_read_oneshot()
, and redcap_read_oneshot_eav()
always return Linux-style line endings (ie \n
) instead of Windows style line endings (ie, \r\n
) on all OSes. (#198)read_metadata()
always returns character
vectors for all variables. With readr 1.2.0, some column were returned differently than before. (#193)redcap_users_export()
now included (#163)redcap_read()
, redcap_read_oneshot()
, & redcap_read_oneshot_eav()
(#206). It was already implemented for redcap_metadata_read()
.redcap_read()
, redcap_read_oneshot()
, & redcap_read_oneshot_eav()
(#206). It was already implemented for redcap_metadata_read()
.constants()
) easily exposes REDCap-specific constants. (#217)id_position
allows user to specify if the record_id isn’t in the first position (#207). However, we recommend that all REDCap projects keep this important variable first in the data dictionary.id_position
allows user to specify if the record_id isnât in the first position (#207). However, we recommend that all REDCap projects keep this important variable first in the data dictionary.
redcap_read()
and redcap_read_oneshot()
are more consistent with the order in raw REDCap API. (#204)verbose
parameter is NULL, then the value from getOption(“verbose”) is used. (#215)verbose
parameter is NULL, then the value from getOption(âverboseâ) is used. (#215)guess_max
parameter provided in redcap_read()
(no longer just redcap_read_oneshot()
). Suggested by @isaactpetersen in #245.kernal_api()
function, which uses the ‘httr’ and ‘curl’ packages underneath. Until now, each function called those packages directly. (#213)readr::read_csv()
is used instead of utils::read.csv()
(Issue #127).kernal_api()
function, which uses the âhttrâ and âcurlâ packages underneath. Until now, each function called those packages directly. (#213)readr::read_csv()
is used instead of utils::read.csv()
(Issue #127).odbc
package to retrieve credentials from the token server. Remove RODBC and RODBCext (#188). Thanks to @krlmlr for error checking advice in https://stackoverflow.com/a/50419403/1082435.data.table::rbindlist()
is used. This should prevent errors with the first batch’s data type (for a column) isn’t compatible with a later batch. For instance, this occurs when the first batch has only integers for record_id
, but a subsequent batch has values like aa-test-aa
. The variable for the combined dataset should be a character. (Issue #128 & http://stackoverflow.com/questions/39377370/bind-rows-of-different-data-types; Thanks @arunsrinivasan)dplyr
package instead of plyr
. This shouldn’t affect callers, because immediately before returning the data, REDCapR::redcap_read()
coerces the tibble::tibble
(which was formerly called dplyr::tbl_df
) back to a vanilla data.frame
with as.data.frame()
.data.table::rbindlist()
is used. This should prevent errors with the first batchâs data type (for a column) isnât compatible with a later batch. For instance, this occurs when the first batch has only integers for record_id
, but a subsequent batch has values like aa-test-aa
. The variable for the combined dataset should be a character. (Issue #128 & http://stackoverflow.com/questions/39377370/bind-rows-of-different-data-types; Thanks @arunsrinivasan)dplyr
package instead of plyr
. This shouldnât affect callers, because immediately before returning the data, REDCapR::redcap_read()
coerces the tibble::tibble
(which was formerly called dplyr::tbl_df
) back to a vanilla data.frame
with as.data.frame()
.requireNamespace()
instead of require()
.requireNamespace()
instead of require()
.readcap_read()
is being used without ‘Full Data Set’ export privileges. The problem involves the record IDs are hashed.readcap_read()
is being used without âFull Data Setâ export privileges. The problem involves the record IDs are hashed.id_position
in the first stage of batching. The metadata needed to be read before that, after the updates for REDCap Version 6.0.x.retrieve_token_mssql()
uses regexes to validate parameterstestthat::skip_on_cran()
before any call involving OUHSC’s REDCap server.testthat::skip_on_cran()
before any call involving OUHSCâs REDCap server.redcap_download_file_oneshot()
documentation, thanks to Andrew Peters (@ARPeters #45).status_message
to outcome_message
. This is because the message associated with http code returned is conventionally called the ‘status messages’ (eg, OK, Forbidden, Not Found).raw_text
value (which was formerly called raw_csv
) is returned as an empty string to save RAM. It’s not really necessary with httr’s status message exposed.status_message
to outcome_message
. This is because the message associated with http code returned is conventionally called the âstatus messagesâ (eg, OK, Forbidden, Not Found).raw_text
value (which was formerly called raw_csv
) is returned as an empty string to save RAM. Itâs not really necessary with httrâs status message exposed.+REDCapR:::collapse_vector(elements=NULL, collapsed=NULL)library(REDCapR) #Load the package into the current R session. -REDCapR:::collapse_vector(elements=NULL, collapsed=NULL)#> [1] ""#> [1] "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"#> [1] "4,5,6"
#> [1] 0#> [1] 1#> [1] 2#> [1] 0#> [1] 1#> [1] 2#> [1] 0#> [1] 2#> [1] 1#> [1] 3#> [1] 0#> [1] 1-REDCapR::constant(c( +- @@ -264,7 +242,7 @@REDCapR::constant("form_incomplete") # Returns 0L#> [1] 0REDCapR::constant("form_unverified") # Returns 1L#> [1] 1REDCapR::constant("form_complete" ) # Returns 2L#> [1] 2+REDCapR::constant("data_export_rights_no_access" ) # Returns 0L#> [1] 0REDCapR::constant("data_export_rights_deidentified") # Returns 1L#> [1] 1REDCapR::constant("data_export_rights_full" ) # Returns 2L#> [1] 2+REDCapR::constant("form_rights_no_access") # Returns 0L#> [1] 0REDCapR::constant("form_rights_readonly" ) # Returns 2L --Notice the order#> [1] 2REDCapR::constant("form_rights_edit_form") # Returns 1L#> [1] 1REDCapR::constant("form_rights_edit_survey") # Returns 3L#> [1] 3+REDCapR::constant("access_no" ) # Returns 0L#> [1] 0REDCapR::constant("access_yes") # Returns 1L#> [1] 1+REDCapR::constant(c( "form_complete", "form_complete", "form_incomplete" -)) # Returns c(2L, 2L, 0L)#> [1] 2 2 0#> [1] 2 2 0REDCapR::constant(c( "form_rights_no_access", "form_rights_readonly", "form_rights_edit_form", @@ -238,22 +223,15 @@Examp # {'form_complete','form_incomplete','form_unverified'}, # but is {'bad-name'}. -REDCapR::constant("bad-name") # Returns an error +REDCapR::constant("bad-name") # Returns an error -REDCapR::constant(c("form_complete", "bad-name")) # Returns an error +REDCapR::constant(c("form_complete", "bad-name")) # Returns an error }
Author
See redcap_read()
for a function that uses create_batch_gloassary
.
#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty +- @@ -330,7 +307,7 @@REDCapR::create_batch_glossary(100, 50)#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty #> 1 1 1 50 1 001 050 #> 2 2 51 100 2 051 100 #> label #> 1 1_001_050 -#> 2 2_051_100#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty +#> 2 2_051_100REDCapR::create_batch_glossary(100, 25)#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty #> 1 1 1 25 1 001 025 #> 2 2 26 50 2 026 050 #> 3 3 51 75 3 051 075 @@ -225,7 +210,7 @@Examp #> 1 1_001_025 #> 2 2_026_050 #> 3 3_051_075 -#> 4 4_076_100
#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty +#> 4 4_076_100REDCapR::create_batch_glossary(100, 3)#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty #> 1 1 1 3 01 001 003 #> 2 2 4 6 02 004 006 #> 3 3 7 9 03 007 009 @@ -299,7 +284,7 @@Examp iv = sample(x=4, size=100, replace=TRUE), dv = rnorm(n=100) ) -REDCapR::create_batch_glossary(nrow(d), batch_size=40)
#> id start_index stop_index index_pretty start_index_pretty stop_index_pretty +REDCapR::create_batch_glossary(nrow(d), batch_size=40)Author
Reading and writing REDCap records, and files within a record.
+ + + + +Accessing other information from the REDCap project or server.
Download a file from a REDCap project record
Functions and classes used by the methods above.
Responsibly store and retrieve a user’s project-specific token.
+Responsibly store and retrieve a userâs project-specific token.
Functions to help the methods above.
The name of the event where the file is saved in REDCap. +Optional
The name of the instrument that is repeating +for a given event. +Optional
(only for projects with repeating instruments/events) +The repeat instance number of the repeating event (if longitudinal) or the +repeating instrument (if classic or longitudinal). Default value is '1'. Optional
Will Beasley, John J. Aponte
+if (FALSE) { uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "9A81268476645C4E5F03428B8AC3AA7B" -REDCapR::redcap_metadata_read(redcap_uri=uri, token=token) +REDCapR::redcap_metadata_read(redcap_uri=uri, token=token) }
+REDCapR::redcap_next_free_record_name(redcap_uri = uri, token = token)uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "9A81268476645C4E5F03428B8AC3AA7B" # Returns 6 -REDCapR::redcap_next_free_record_name(redcap_uri = uri, token = token)#> The next free record name in REDCap was successfully determined in 0.2 seconds. The http status code was 200. Is is 6.#> [1] "6"
redcap_uri
The URI (uniform resource identifier) of the REDCap project. Required.
read(
batch_size = 100L,
interbatch_delay = 0,
@@ -221,7 +206,7 @@ Examp
uri <- "https://bbmc.ouhsc.edu/redcap/api/"
token <- "D70F9ACD1EDD6F151C6EA78683944E98"
if (FALSE) {
-project <- REDCapR::redcap_project$new(redcap_uri=uri, token=token)
+project <- REDCapR::redcap_project$new(redcap_uri=uri, token=token)
ds_all <- project$read()
# Demonstrate how repeated calls are more concise when the token and
@@ -244,14 +229,10 @@ Examp
project$write(ds_skinny)
}
if (FALSE) { uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "9A81268476645C4E5F03428B8AC3AA7B" -REDCapR::redcap_read(batch_size=2, redcap_uri=uri, token=token)$data +REDCapR::redcap_read(batch_size=2, redcap_uri=uri, token=token)$data # Specify the column types. col_types <- readr::cols( @@ -415,7 +400,7 @@Examp race___5 = readr::col_logical(), race___6 = readr::col_logical() ) -REDCapR::redcap_read( +REDCapR::redcap_read( redcap_uri = uri, token = token, col_types = col_types, @@ -424,18 +409,10 @@
Examp }
Will Beasley, John J. Aponte
+uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "06DEFB601F9B46847DAA9DF0CFA951B4" -result <- REDCapR::redcap_users_export(redcap_uri=uri, token=token)#> The REDCap users were successfully exported in 0.3 seconds. The http status code was 200.result$data_user#> # A tibble: 2 x 31 +result <- REDCapR::redcap_users_export(redcap_uri=uri, token=token)#> The REDCap users were successfully exported in 0.2 seconds. The http status code was 200.result$data_user#> # A tibble: 2 x 31 #> username email firstname lastname expiration data_access_gro… data_access_gro… #> <chr> <chr> <chr> <chr> <date> <chr> <chr> #> 1 unittes… wibe… Unit Test PHI Free NA daga 331 #> 2 wbeasle… will… Will Beasley… NA NA NA -#> # … with 24 more variables: design <lgl>, user_rights <lgl>, -#> # data_access_groups <lgl>, data_export <chr>, reports <lgl>, -#> # stats_and_charts <lgl>, manage_survey_participants <lgl>, calendar <lgl>, -#> # data_import_tool <lgl>, data_comparison_tool <lgl>, logging <lgl>, -#> # file_repository <lgl>, data_quality_create <lgl>, -#> # data_quality_execute <lgl>, api_export <lgl>, api_import <lgl>, -#> # mobile_app <lgl>, mobile_app_download_data <lgl>, record_create <lgl>, -#> # record_rename <lgl>, record_delete <lgl>, lock_records_all_forms <lgl>, -#> # lock_records <lgl>, lock_records_customization <lgl>result$data_user_form#> # A tibble: 2 x 4 +#> # … with 24 more variables: design <lgl>, user_rights <lgl>, +#> # data_access_groups <lgl>, data_export <chr>, reports <lgl>, +#> # stats_and_charts <lgl>, manage_survey_participants <lgl>, calendar <lgl>, +#> # data_import_tool <lgl>, data_comparison_tool <lgl>, logging <lgl>, +#> # file_repository <lgl>, data_quality_create <lgl>, +#> # data_quality_execute <lgl>, api_export <lgl>, api_import <lgl>, +#> # mobile_app <lgl>, mobile_app_download_data <lgl>, record_create <lgl>, +#> # record_rename <lgl>, record_delete <lgl>, lock_records_all_forms <lgl>, +#> # lock_records <lgl>, lock_records_customization <lgl>result$data_user_form#> # A tibble: 2 x 4 #> username form_name permission_id permission #> <chr> <chr> <int> <fct> #> 1 unittestphifree demographics 1 edit_form #> 2 wbeasleya demographics 1 edit_form
if (FALSE) { uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "9A81268476645C4E5F03428B8AC3AA7B" -ds_variable <- REDCapR::redcap_variables(redcap_uri=uri, token=token)$data +ds_variable <- REDCapR::redcap_variables(redcap_uri=uri, token=token)$data }
+REDCapR::redcap_version(redcap_uri = uri, token = token)uri <- "https://bbmc.ouhsc.edu/redcap/api/" token <- "9A81268476645C4E5F03428B8AC3AA7B" -REDCapR::redcap_version(redcap_uri = uri, token = token)#> The REDCap version was successfully determined in 0.3 seconds. The http status code was 200. Is is 9.0.0.#> [1] ‘9.0.0’
# ---- Local File Example ---------------------------- path <- system.file("misc/example.credentials", package = "REDCapR") -(p1 <- REDCapR::retrieve_credential_local(path, 153L))#> $redcap_uri +(p1 <- REDCapR::retrieve_credential_local(path, 153L))#> $redcap_uri #> [1] "https://bbmc.ouhsc.edu/redcap/api/" #> #> $username @@ -266,7 +251,7 @@Examp #> #> $comment #> [1] "simple static (read-only) test project" -#>
#> $redcap_uri +#>(p2 <- REDCapR::retrieve_credential_local(path, 212L))
+REDCapR::sanitize_token(secret_token_1)secret_token_1 <- "12345678901234567890123456ABCDEF" secret_token_2 <- "12345678901234567890123456ABCDEF\n" -REDCapR::sanitize_token(secret_token_1)#> [1] "12345678901234567890123456ABCDEF"#> [1] "12345678901234567890123456ABCDEF"
Hao Zhu, Benjamin Nutter, Will Beasley
+