# Basic REDCapR Operations

#### 2022-08-10

This vignette covers the the basic functions exposed by the `httr` and `curl` packages which allow you to interact with REDCap through its API.

# Reading REDCap Data

The function `redcap_read_oneshot` uses the `httr` package to call the REDCap API.

    ## Loading required namespace: kableExtra

## Set project-wide values

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)

## Read all records and fields

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 17 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.1 seconds.  The http status code was 200.

    Starting to read 5 records  at 2022-08-10 09:24:47.

    Reading batch 1 of 1, with subjects 1 through 5 (ie, 5 unique subject records).

    5 records and 25 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    ── Column specification ────────────────────────────────────────────────────────
    cols(
      .default = col_double(),
      name_first = col_character(),
      name_last = col_character(),
      address = col_character(),
      telephone = col_character(),
      email = col_character(),
      dob = col_date(format = ""),
      comments = col_character(),
      mugshot = col_character()
    )
    ℹ Use `spec()` for the 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
    3         3     Marcus      Wood          243 Hill St.\nGuthrie OK 73402
    4         4      Trudy       DAG          342 Elm\nDuncanville TX, 75116
    5         5   John Lee    Walker      Hotel Suite\nNew Orleans LA, 70115
           telephone               email        dob age sex demographics_complete
    1 (405) 321-1111     nutty@mouse.com 2003-08-30  11   0                     2
    2 (405) 321-2222    tummy@mouse.comm 2003-03-10  11   1                     2
    3 (405) 321-3333        mw@mwood.net 1934-04-09  80   1                     2
    4 (405) 321-4444 peroxide@blonde.com 1952-11-02  61   0                     2
    5 (405) 321-5555  left@hippocket.com 1955-04-15  59   1                     2
      height weight   bmi
    1   7.00      1 204.1
    2   6.00      1 277.8
    3 180.00     80  24.7
    4 165.00     54  19.8
    5 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
            mugshot health_complete race___1 race___2 race___3 race___4 race___5
    1 mugshot-1.jpg               1        0        0        0        0        1
    2 mugshot-2.jpg               0        0        0        1        0        1
    3 mugshot-3.jpg               2        0        0        0        1        1
    4 mugshot-4.jpg               2        0        1        0        0        1
    5 mugshot-5.jpg               0        1        0        0        0        0
      race___6 ethnicity interpreter_needed race_and_ethnicity_complete
    1        0         1                  0                           2
    2        0         1                  0                           0
    3        0         0                  1                           2
    4        0         1                 NA                           2
    5        1         2                  0                           2

## 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 17 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 2022-08-10 09:24:48.

    Reading batch 1 of 1, with subjects 1 through 3 (ie, 2 unique subject records).

    2 records and 25 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    ── Column specification ────────────────────────────────────────────────────────
    cols(
      .default = col_double(),
      name_first = col_character(),
      name_last = col_character(),
      address = col_character(),
      telephone = col_character(),
      email = col_character(),
      dob = col_date(format = ""),
      comments = col_character(),
      mugshot = col_character()
    )
    ℹ Use `spec()` for the 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 17 fields was read from REDCap in 0.1 seconds.  The http status code was 200.

    2 records and 1 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    Starting to read 2 records  at 2022-08-10 09:24:50.

    Reading batch 1 of 1, with subjects 1 through 3 (ie, 2 unique subject records).

    2 records and 25 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    ── Column specification ────────────────────────────────────────────────────────
    cols(
      .default = col_double(),
      name_first = col_character(),
      name_last = col_character(),
      address = col_character(),
      telephone = col_character(),
      email = col_character(),
      dob = col_date(format = ""),
      comments = col_character(),
      mugshot = col_character()
    )
    ℹ Use `spec()` for the 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
           telephone           email        dob age sex demographics_complete
    1 (405) 321-1111 nutty@mouse.com 2003-08-30  11   0                     2
    2 (405) 321-3333    mw@mwood.net 1934-04-09  80   1                     2
      height weight   bmi                                comments       mugshot
    1      7      1 204.1 Character in a book, with some guessing mugshot-1.jpg
    2    180     80  24.7                      completely made up mugshot-3.jpg
      health_complete race___1 race___2 race___3 race___4 race___5 race___6
    1               1        0        0        0        0        1        0
    2               2        0        0        0        1        1        0
      ethnicity interpreter_needed race_and_ethnicity_complete
    1         1                  0                           2
    2         0                  1                           2

## 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 17 fields was read from REDCap in 0.1 seconds.  The http status code was 200.

    5 records and 1 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    Starting to read 5 records  at 2022-08-10 09:24:51.

    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.1 seconds.  The http status code was 200.

    ── 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 17 fields was read from REDCap in 0.1 seconds.  The http status code was 200.

    5 records and 1 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    Starting to read 5 records  at 2022-08-10 09:24:52.

    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.1 seconds.  The http status code was 200.

    ── 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
    3         3     Marcus  80
    4         4      Trudy  61
    5         5   John Lee  59

## 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 17 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.1 seconds.  The http status code was 200.

    Starting to read 5 records  at 2022-08-10 09:24:53.

    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.1 seconds.  The http status code was 200.

    ── 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

    [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 17 fields was read from REDCap in 0.1 seconds.  The http status code was 200.

    2 records and 1 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    Starting to read 2 records  at 2022-08-10 09:24:54.

    Reading batch 1 of 1, with subjects 3 through 5 (ie, 2 unique subject records).

    2 records and 25 columns were read from REDCap in 0.1 seconds.  The http status code was 200.

    ── Column specification ────────────────────────────────────────────────────────
    cols(
      .default = col_double(),
      name_first = col_character(),
      name_last = col_character(),
      address = col_character(),
      telephone = col_character(),
      email = col_character(),
      dob = col_date(format = ""),
      comments = col_character(),
      mugshot = col_character()
    )
    ℹ Use `spec()` for the 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
           telephone              email        dob age sex demographics_complete
    1 (405) 321-3333       mw@mwood.net 1934-04-09  80   1                     2
    2 (405) 321-5555 left@hippocket.com 1955-04-15  59   1                     2
      height weight  bmi
    1 180.00     80 24.7
    2 193.04    104 27.9
                                                                                         comments
    1                                                                          completely made up
    2 Had a hand for trouble and a eye for cash\n\nHe had a gold watch chain and a black mustache
            mugshot health_complete race___1 race___2 race___3 race___4 race___5
    1 mugshot-3.jpg               2        0        0        0        1        1
    2 mugshot-5.jpg               0        1        0        0        0        0
      race___6 ethnicity interpreter_needed race_and_ethnicity_complete
    1        0         0                  1                           2
    2        1         2                  0                           2

## Additional Returned Information

The examples above have shown only the resulting `data.frame`, by specifying `$data` at the end of the call. However, more is available to those wanting additional information, such as:

1. The `data` object has the `data.frame`, as in the previous examples.
2. The `success` boolean value indicates if `redcap_read_oneshot` believes the operation completed as intended.
3. The `status_codes` is a collection of http status codes, separated by semicolons. There is one code for each batch attempted.
4. The `outcome_messages`: A collection of human readable strings indicating the operations’ semicolons. There is one code for each batch attempted. In an unsuccessful operation, it should contain diagnostic information.
5. The `records_collapsed` field passed to the API. This shows which record subsets, if any, were requested.
6. The `fields_collapsed` fields passed to the API. This shows which field subsets, if any, were requested.
7. 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 17 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.1 seconds.  The http status code was 200.

    Starting to read 5 records  at 2022-08-10 09:24:55.

    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.2 seconds.  The http status code was 200.

    ── 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
    2         2     Tumtum  11
    3         3     Marcus  80
    4         4      Trudy  61
    5         5   John Lee  59

    $success
    [1] TRUE

    $status_codes
    [1] "200"

    $outcome_messages
    [1] "5 records and 3 columns were read from REDCap in 0.2 seconds.  The http status code was 200."

    $records_collapsed
    [1] ""

    $fields_collapsed
    [1] "record_id,name_first,age"

    $forms_collapsed
    [1] ""

    $events_collapsed
    [1] ""

    $filter_logic
    [1] ""

    $datetime_range_begin
    [1] NA

    $datetime_range_end
    [1] NA

    $elapsed_seconds
    [1] 1.145227

# Session Information

For the sake of documentation and reproducibility, the current report was rendered in the following environment. Click the line below to expand.

Environment

    ─ Session info ───────────────────────────────────────────────────────────────
     setting  value
     version  R version 4.2.0 (2022-04-22)
     os       Ubuntu 22.04.1 LTS
     system   x86_64, linux-gnu
     ui       X11
     language (EN)
     collate  C
     ctype    en_US.UTF-8
     tz       America/Chicago
     date     2022-08-10
     pandoc   2.18 @ /usr/lib/rstudio/bin/quarto/bin/tools/ (via rmarkdown)

    ─ Packages ───────────────────────────────────────────────────────────────────
     package     * version date (UTC) lib source
     archive       1.1.5   2022-05-06 [3] CRAN (R 4.2.0)
     assertthat    0.2.1   2019-03-21 [3] CRAN (R 4.2.0)
     backports     1.4.1   2021-12-13 [3] CRAN (R 4.2.0)
     bit           4.0.4   2020-08-04 [3] CRAN (R 4.2.0)
     bit64         4.0.5   2020-08-30 [3] CRAN (R 4.2.0)
     bslib         0.4.0   2022-07-16 [3] CRAN (R 4.2.0)
     cachem        1.0.6   2021-08-19 [3] CRAN (R 4.2.0)
     checkmate     2.1.0   2022-04-21 [3] CRAN (R 4.2.0)
     cli           3.3.0   2022-04-25 [3] CRAN (R 4.2.0)
     colorspace    2.0-3   2022-02-21 [3] CRAN (R 4.2.0)
     crayon        1.5.1   2022-03-26 [3] CRAN (R 4.2.0)
     curl          4.3.2   2021-06-23 [3] CRAN (R 4.2.0)
     DBI           1.1.3   2022-06-18 [3] CRAN (R 4.2.0)
     digest        0.6.29  2021-12-01 [3] CRAN (R 4.2.0)
     dplyr         1.0.9   2022-04-28 [3] CRAN (R 4.2.0)
     ellipsis      0.3.2   2021-04-29 [3] CRAN (R 4.2.0)
     evaluate      0.16    2022-08-09 [3] CRAN (R 4.2.0)
     fansi         1.0.3   2022-03-24 [3] CRAN (R 4.2.0)
     fastmap       1.1.0   2021-01-25 [3] CRAN (R 4.2.0)
     generics      0.1.3   2022-07-05 [3] CRAN (R 4.2.0)
     glue          1.6.2   2022-02-24 [3] CRAN (R 4.2.0)
     hms           1.1.1   2021-09-26 [3] CRAN (R 4.2.0)
     htmltools     0.5.3   2022-07-18 [3] CRAN (R 4.2.0)
     httr          1.4.3   2022-05-04 [3] CRAN (R 4.2.0)
     jquerylib     0.1.4   2021-04-26 [3] CRAN (R 4.2.0)
     jsonlite      1.8.0   2022-02-22 [3] CRAN (R 4.2.0)
     kableExtra    1.3.4   2021-02-20 [3] CRAN (R 4.2.0)
     knitr       * 1.39    2022-04-26 [3] CRAN (R 4.2.0)
     lifecycle     1.0.1   2021-09-24 [3] CRAN (R 4.2.0)
     magrittr    * 2.0.3   2022-03-30 [3] CRAN (R 4.2.0)
     munsell       0.5.0   2018-06-12 [3] CRAN (R 4.2.0)
     pillar        1.8.0   2022-07-18 [3] CRAN (R 4.2.0)
     pkgconfig     2.0.3   2019-09-22 [3] CRAN (R 4.2.0)
     purrr         0.3.4   2020-04-17 [3] CRAN (R 4.2.0)
     R6            2.5.1   2021-08-19 [3] CRAN (R 4.2.0)
     readr         2.1.2   2022-01-30 [3] CRAN (R 4.2.0)
     REDCapR     * 1.1.0   2022-08-10 [1] local
     rlang         1.0.4   2022-07-12 [3] CRAN (R 4.2.0)
     rmarkdown     2.14    2022-04-25 [3] CRAN (R 4.2.0)
     rstudioapi    0.13    2020-11-12 [3] CRAN (R 4.2.0)
     rvest         1.0.2   2021-10-16 [3] CRAN (R 4.2.0)
     sass          0.4.2   2022-07-16 [3] CRAN (R 4.2.0)
     scales        1.2.0   2022-04-13 [3] CRAN (R 4.2.0)
     sessioninfo   1.2.2   2021-12-06 [3] CRAN (R 4.2.0)
     stringi       1.7.8   2022-07-11 [3] CRAN (R 4.2.0)
     stringr       1.4.0   2019-02-10 [3] CRAN (R 4.2.0)
     svglite       2.1.0   2022-02-03 [3] CRAN (R 4.2.0)
     systemfonts   1.0.4   2022-02-11 [3] CRAN (R 4.2.0)
     tibble        3.1.8   2022-07-22 [3] CRAN (R 4.2.0)
     tidyselect    1.1.2   2022-02-21 [3] CRAN (R 4.2.0)
     tzdb          0.3.0   2022-03-28 [3] CRAN (R 4.2.0)
     utf8          1.2.2   2021-07-24 [3] CRAN (R 4.2.0)
     vctrs         0.4.1   2022-04-13 [3] CRAN (R 4.2.0)
     viridisLite   0.4.0   2021-04-13 [3] CRAN (R 4.2.0)
     vroom         1.5.7   2021-11-30 [3] CRAN (R 4.2.0)
     webshot       0.5.3   2022-04-14 [3] CRAN (R 4.2.0)
     withr         2.5.0   2022-03-03 [3] CRAN (R 4.2.0)
     xfun          0.32    2022-08-10 [3] CRAN (R 4.2.0)
     xml2          1.3.3   2021-11-30 [3] CRAN (R 4.2.0)
     yaml          2.3.5   2022-02-21 [3] CRAN (R 4.2.0)

     [1] /tmp/RtmpSYJzex/Rinst29b36238315a1
     [2] /tmp/RtmplvH3JR/temp_libpath1796625c20c6
     [3] /home/wibeasley/R/x86_64-pc-linux-gnu-library/4.2
     [4] /usr/local/lib/R/site-library
     [5] /usr/lib/R/site-library
     [6] /usr/lib/R/library

    ──────────────────────────────────────────────────────────────────────────────

Report rendered by wibeasley at 2022-08-10, 09:24 -0500 in 13 seconds.