Deploying to gh-pages from @ agdamsbo/REDCapCAST@db75c3313e 🚀

This commit is contained in:
agdamsbo 2025-11-14 14:10:52 +00:00
commit 0b30252598
171 changed files with 7009 additions and 602 deletions

View file

@ -1,17 +1,16 @@
<!DOCTYPE html>
<!-- Generated by pkgdown: do not edit by hand --><html lang="en">
<!-- Generated by pkgdown: do not edit by hand --><html lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Database-creation • REDCapCAST</title>
<!-- favicons --><link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="../favicon-32x32.png">
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="../apple-touch-icon.png">
<link rel="apple-touch-icon" type="image/png" sizes="120x120" href="../apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" type="image/png" sizes="76x76" href="../apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" type="image/png" sizes="60x60" href="../apple-touch-icon-60x60.png">
<!-- favicons --><link rel="icon" type="image/png" sizes="96x96" href="../favicon-96x96.png">
<link rel="icon" type="”image/svg+xml”" href="../favicon.svg">
<link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon.png">
<link rel="icon" sizes="any" href="../favicon.ico">
<link rel="manifest" href="../site.webmanifest">
<script src="../deps/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="../deps/bootstrap-5.3.1/bootstrap.min.css" rel="stylesheet">
<script src="../deps/bootstrap-5.3.1/bootstrap.bundle.min.js"></script><link href="../deps/font-awesome-6.5.2/css/all.min.css" rel="stylesheet">
@ -26,7 +25,7 @@
<a class="navbar-brand me-2" href="../index.html">REDCapCAST</a>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.3.2</small>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.11.1</small>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
@ -67,7 +66,7 @@
<h1>Database-creation</h1>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/v25.3.2/vignettes/Database-creation.Rmd" class="external-link"><code>vignettes/Database-creation.Rmd</code></a></small>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/main/vignettes/Database-creation.Rmd" class="external-link"><code>vignettes/Database-creation.Rmd</code></a></small>
<div class="d-none name"><code>Database-creation.Rmd</code></div>
</div>
@ -187,7 +186,7 @@ upload: manual or through <code>REDCapR</code>.</p>
</div>
<div class="pkgdown-footer-right">
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.1.1.</p>
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.2.0.</p>
</div>
</footer>

View file

@ -0,0 +1,117 @@
# Database-creation
``` r
library(REDCapCAST)
```
## Two different ways to create a data base
`REDCapCAST` provides two approaches to creating a data dictionary aimed
at helping out in two different cases:
1. Easily create a REDCap data base from an existing data set.
2. Create a table in Word describing a variables in a data base and use
this to create a data base.
In the following I will try to come with a few suggestions on how to use
these approaches.
### Easy data set to data base workflow
The first iteration of a dataset to data dictionary function is the
[`ds2dd()`](https://agdamsbo.github.io/REDCapCAST/reference/ds2dd.md),
which creates a very basic data dictionary with all variables stored as
text. This is sufficient for just storing old datasets/spreadsheets
securely in REDCap.
``` r
d1 <- mtcars |>
dplyr::mutate(record_id = seq_len(dplyr::n())) |>
ds2dd()
d1 |>
gt::gt()
```
The more advanced
[`ds2dd_detailed()`](https://agdamsbo.github.io/REDCapCAST/reference/ds2dd_detailed.md)
is a natural development. It will try to apply the most common data
classes for data validation and will assume that the first column is the
id number. It outputs a list with the dataset with modified variable
names to comply with REDCap naming conventions and a data dictionary.
The dataset should be correctly formatted for the data dictionary to
preserve as much information as possible.
``` r
d2 <- REDCapCAST::redcapcast_data |>
dplyr::mutate(record_id = seq_len(dplyr::n()),
region=factor(region)) |>
dplyr::select(record_id, dplyr::everything()) |>
(\(.x){
.x[!grepl("_complete$",names(.x))]
})() |>
(\(.x){
.x[!grepl("^redcap",names(.x))]
})() |>
ds2dd_detailed() |>
purrr::pluck("meta")
d2 |>
gt::gt()
```
Additional specifications to the DataDictionary can be made manually, or
it can be uploaded and modified manually in the graphical user interface
on the REDCap server.
### Data base from table
…instructions and examples are coming…
### Meta data and data upload
Now the DataDictionary can be exported as a spreadsheet and uploaded or
it can be uploaded using the `REDCapR` package (only projects with
“Development” status).
Use one of the two approaches below:
#### Manual upload
``` r
write.csv(dd_ls$meta, "datadictionary.csv")
```
#### Upload with `REDCapR`
``` r
REDCapR::redcap_metadata_write(
dd_ls$meta,
redcap_uri = keyring::key_get("DB_URI"),
token = keyring::key_get("DB_TOKEN")
)
```
In the [“REDCap R
Handbook”](https://agdamsbo.github.io/redcap-r-handbook/) more is
written on interfacing with REDCap in R using the
[`library(keyring)`](https://keyring.r-lib.org/)to store credentials in
[chapter
1.1](https://agdamsbo.github.io/redcap-r-handbook/doc/access.html#sec-getting-access).
### Step 4 - Data upload
The same two options are available for data upload as meta data upload:
manual or through `REDCapR`.
Only the latter is shown here.
``` r
REDCapR::redcap_write(
dd_ls$data,
redcap_uri = keyring::key_get("DB_URI"),
token = keyring::key_get("DB_TOKEN")
)
```

View file

@ -1,17 +1,16 @@
<!DOCTYPE html>
<!-- Generated by pkgdown: do not edit by hand --><html lang="en">
<!-- Generated by pkgdown: do not edit by hand --><html lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>REDCapCAST • REDCapCAST</title>
<!-- favicons --><link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="../favicon-32x32.png">
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="../apple-touch-icon.png">
<link rel="apple-touch-icon" type="image/png" sizes="120x120" href="../apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" type="image/png" sizes="76x76" href="../apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" type="image/png" sizes="60x60" href="../apple-touch-icon-60x60.png">
<!-- favicons --><link rel="icon" type="image/png" sizes="96x96" href="../favicon-96x96.png">
<link rel="icon" type="”image/svg+xml”" href="../favicon.svg">
<link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon.png">
<link rel="icon" sizes="any" href="../favicon.ico">
<link rel="manifest" href="../site.webmanifest">
<script src="../deps/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="../deps/bootstrap-5.3.1/bootstrap.min.css" rel="stylesheet">
<script src="../deps/bootstrap-5.3.1/bootstrap.bundle.min.js"></script><link href="../deps/font-awesome-6.5.2/css/all.min.css" rel="stylesheet">
@ -26,7 +25,7 @@
<a class="navbar-brand me-2" href="../index.html">REDCapCAST</a>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.3.2</small>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.11.1</small>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
@ -67,7 +66,7 @@
<h1>REDCapCAST</h1>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/v25.3.2/vignettes/REDCapCAST.Rmd" class="external-link"><code>vignettes/REDCapCAST.Rmd</code></a></small>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/main/vignettes/REDCapCAST.Rmd" class="external-link"><code>vignettes/REDCapCAST.Rmd</code></a></small>
<div class="d-none name"><code>REDCapCAST.Rmd</code></div>
</div>
@ -2984,7 +2983,7 @@ format):</p>
<td headers="stat_0" class="gt_row gt_center">5</td>
</tr>
</tbody>
<tfoot class="gt_footnotes"><tr>
<tfoot><tr class="gt_footnotes">
<td class="gt_footnote" colspan="2">
<span class="gt_footnote_marks" style="white-space:nowrap;font-style:italic;font-weight:normal;line-height:0;"><sup>1</sup></span> <span class="gt_from_md">n (%)</span>
</td>
@ -3003,7 +3002,7 @@ format):</p>
</div>
<div class="pkgdown-footer-right">
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.1.1.</p>
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.2.0.</p>
</div>
</footer>

357
articles/REDCapCAST.md Normal file
View file

@ -0,0 +1,357 @@
# REDCapCAST
``` r
library(REDCapCAST)
```
This vignette covers the basics to get you started with the two basic
features of REDCapCAST:
- Casting REDCap metadata to create a new REDCap database or extend an
existing with a new instrument
- Reading REDCap data in a convenient and focused way, by only getting
the data you need, while preserving as much metadata as possible.
## Casting meta data
The easiest way is to use the
[`shiny_cast()`](https://agdamsbo.github.io/REDCapCAST/reference/shiny_cast.md).
You can access a [hosted version
here](https://agdamsbo.shinyapps.io/redcapcast/) or launch it locally
like this:
``` r
shiny_cast()
```
## Reading data from REDCap
To get you started, the easiest way possible, you can use the
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
function (example below).
You will need an API-key for your REDCap server, the uri/URL/address for
the API connection (usually the address used for accessing your
institutions REDCap server, with an appended “/api/”).
This function includes a few convenience features to ease your further
work.
If your project uses repeating instruments possible as a longitudinal
project, you can choose to widen the data. If not, the result will be a
list of each instrument you have chosen to extract data from. Make sure
to specify only the fields or instruments you need, and avoid to save
any of the data locally, but always source from REDCap to avoid possibly
insecure local storage of sensitive data.
``` r
easy_redcap(
uri = "YOUR URI",
project.name = "MY_PROJECT",
widen.data = TRUE,
fields = c("record_id", "OTHER FIELDS")
)
```
## Splitting the dataset
The
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
function does a few things under the hood. Below are a few examples to
show how the nicely formatted output is achieved.
A sample dataset and Data Dictionary/metadata is provided for this
demonstration:
``` r
redcapcast_data |> gt::gt()
```
| record_id | redcap_event_name | redcap_repeat_instrument | redcap_repeat_instance | cpr | inclusion | inclusion_time | dob | age | age_integer | sex | cohabitation | hypertension | diabetes | region | baseline_data_start_complete | mrs_assessed | mrs_date | mrs_score | mrs_complete | con_mrs | con_calc | consensus_complete | event_datetime | event_age | event_type | new_event_complete |
|-----------|-------------------|--------------------------|------------------------|------------|------------|----------------|------------|-----------|-------------|--------|--------------|--------------|----------|--------|------------------------------|--------------|------------|-----------|--------------|---------|----------|--------------------|---------------------|-----------|------------|--------------------|
| 1 | inclusion | NA | NA | 1203401OB4 | 2023-03-13 | 12:38:49 | 1940-03-12 | 83.00239 | 83 | female | Yes | No | Yes | East | Incomplete | Yes | 2023-03-13 | 1 | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 2 | inclusion | NA | NA | 0102342303 | 2023-03-01 | 10:38:57 | 1934-02-01 | 89.07780 | 89 | male | Yes | No | No | South | Incomplete | Yes | 2023-03-07 | 1 | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 2 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2023-03-09 | 3 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 2 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:49:42 | NA | TIA | Incomplete |
| 3 | inclusion | NA | NA | 2301569823 | 2022-03-08 | 12:01:07 | 1956-01-23 | 66.12319 | 66 | male | No | Yes | Yes | North | Incomplete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 3 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2022-08-16 | 2 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 3 | follow2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Yes | 2023-03-13 | 1 | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 3 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:49:58 | NA | AIS | Incomplete |
| 3 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:01 | NA | ICH | Incomplete |
| 3 | follow2 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:05 | NA | ICH | Incomplete |
| 3 | follow2 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:07 | NA | TIA | Incomplete |
| 3 | follow2 | New Event (?) | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:09 | NA | AIS | Incomplete |
| 4 | inclusion | NA | NA | 0204051342 | 2023-03-14 | 20:39:19 | 1905-04-02 | 117.94903 | 117 | female | NA | NA | NA | NA | Incomplete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 4 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 4 | follow2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 4 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2001-04-11 08:39:05 | 96 | TIA | Complete |
| 4 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2010-04-11 08:39:25 | 105 | TIA | Complete |
| 4 | follow2 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:19 | 118 | AIS | Complete |
| 4 | follow2 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:22 | 118 | ICH | Incomplete |
| 4 | follow2 | New Event (?) | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-01-18 12:50:24 | 118 | Unknown | Complete |
| 5 | inclusion | NA | NA | 0201976043 | 2023-03-23 | 08:50:31 | 1897-01-02 | 126.21751 | 126 | male | No | Yes | Yes | East | Complete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
| 5 | follow1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | Incomplete | NA | NA | Incomplete | NA | NA | NA | NA |
| 5 | follow1 | New Event (?) | 1 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-04-11 09:00:33 | 127 | AIS | Complete |
| 5 | follow1 | New Event (?) | 2 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 2024-04-11 09:00:41 | 127 | ICH | Complete |
| 6 | inclusion | NA | NA | 1202320122 | 2024-01-25 | 08:49:28 | 1932-02-12 | 91.95261 | 91 | female | No | Yes | No | East | Complete | NA | NA | NA | Incomplete | NA | NA | NA | NA | NA | NA | NA |
``` r
redcapcast_meta |> gt::gt()
```
| field_name | form_name | section_header | field_type | field_label | select_choices_or_calculations | field_note | text_validation_type_or_show_slider_number | text_validation_min | text_validation_max | identifier | branching_logic | required_field | custom_alignment | question_number | matrix_group_name | matrix_ranking | field_annotation |
|----------------|---------------------|--------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------------------------------------------|---------------------|---------------------|------------|-----------------|----------------|------------------|-----------------|-------------------|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| record_id | baseline_data_start | NA | text | ID | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| cpr | baseline_data_start | NA | text | CPR (Danish civil registration number) | NA | ddmmyyxxxx | NA | NA | NA | y | NA | y | NA | NA | NA | NA | NA |
| inclusion | baseline_data_start | NA | text | Inclusion date | NA | NA | date_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| inclusion_time | baseline_data_start | NA | text | Inclusion time | NA | NA | time_hh_mm_ss | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| dob | baseline_data_start | NA | text | Date of birth (From CPR) | NA | NA | date_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[cpr\]!="", concat(if(mid(\[cpr\], 7, 1)\>=0 and mid(\[cpr\], 7, 1)\<=3,19, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=36 and mid(\[cpr\], 7, 1)\>=4 and mid(\[cpr\], 7, 1)\<=4,20, if(mid(\[cpr\], 5, 2)\>=37 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=4 and mid(\[cpr\], 7, 1)\<=4,19, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=5 and mid(\[cpr\], 7, 1)\<=5,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=5 and mid(\[cpr\], 7, 1)\<=5,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=6 and mid(\[cpr\], 7, 1)\<=6,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=6 and mid(\[cpr\], 7, 1)\<=6,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=7 and mid(\[cpr\], 7, 1)\<=7,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=7 and mid(\[cpr\], 7, 1)\<=7,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=57 and mid(\[cpr\], 7, 1)\>=8 and mid(\[cpr\], 7, 1)\<=8,20, if(mid(\[cpr\], 5, 2)\>=58 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=8 and mid(\[cpr\], 7, 1)\<=8,18, if(mid(\[cpr\], 5, 2)\>=0 and mid(\[cpr\], 5, 2)\<=36 and mid(\[cpr\], 7, 1)\>=9 and mid(\[cpr\], 7, 1)\<=9,20, if(mid(\[cpr\], 5, 2)\>=37 and mid(\[cpr\], 5, 2)\<=99 and mid(\[cpr\], 7, 1)\>=9 and mid(\[cpr\], 7, 1)\<=9,19,17))))))))))))), mid(\[cpr\], 5, 2), "-",mid(\[cpr\],3, 2), "-", left(\[cpr\], 2) ), "")) |
| age | baseline_data_start | NA | calc | Age Note: Apparently, the build in datediff() function does not handle counting whole years. This results in wrongly counting age higher around the date of birth. | if(\[cpr\]!="" and \[inclusion\]!="", datediff(\[dob\], \[inclusion\], 'y'), "") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| age_integer | baseline_data_start | NA | calc | Age integer Note: as opposed to the build in datediff() this handles counting years as integers very well. Calculate decimal years in statistical programming software. In R you can use with(ds, stRoke::age_calc(dob, inclusion)). | if(\[cpr\]!="", left(\[inclusion\], 4)-left(\[dob\], 4) - if(mid(\[dob\], 6, 2) \< mid(\[inclusion\], 6, 2) or (mid(\[dob\], 6, 2) = mid(\[inclusion\], 6, 2) and mid(\[dob\], 9, 2) \<= mid(\[inclusion\], 9, 2)), 0, 1),"") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| sex | baseline_data_start | NA | text | Legal sex | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[cpr\]!="",if((right(\[cpr\],1)=1 or right(\[cpr\],1)=3 or right(\[cpr\],1)=5 or right(\[cpr\],1)=7 or right(\[cpr\],1)=9),"male","female"),"")) |
| cohabitation | baseline_data_start | History and social | radio | Cohabitation | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| hypertension | baseline_data_start | NA | radio | Hypertension | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| diabetes | baseline_data_start | NA | radio | Diabetes | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| region | baseline_data_start | Area | dropdown | Region | 1, North \| 2, East \| 3, South \| 4, West | NA | autocomplete | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_assessed | mrs | NA | radio | Assesed | 1, Yes \| 2, No | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_date | mrs | NA | text | Assessment date | NA | NA | date_dmy | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| mrs_score | mrs | NA | radio | mRS score | 0, 0 \| 1, 1 \| 2, 2 \| 3, 3 \| 4, 4 \| 5, 5 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| con_event_note | consensus | NA | descriptive | \[follow1_arm_1\]\[event_type\]\[1\] : \[follow1_arm_1\]\[event_type\]\[2\] | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| con_mrs | consensus | NA | text | Same event type | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @IF('\[follow1_arm_1\]\[event_type\]\[1\]'='\[follow1_arm_1\]\[event_type\]\[2\]',@DEFAULT='pass',@DEFAULT="fail") |
| con_calc | consensus | NA | text | calc | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | @CALCTEXT(if(\[follow1_arm_1\]\[event_type\]\[1\]=\[follow1_arm_1\]\[event_type\]\[2\],\[follow1_arm_1\]\[event_type\]\[1\],"fail")) |
| event_datetime | new_event | NA | text | Time of event | NA | NA | datetime_seconds_ymd | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| event_age | new_event | NA | calc | Age at event | if(\[event_datetime\]!="", left(\[event_datetime\], 4)-left(\[inclusion_arm_1\]\[dob\], 4) - if(mid(\[inclusion_arm_1\]\[dob\], 6, 2) \< mid(\[event_datetime\], 6, 2) or (mid(\[inclusion_arm_1\]\[dob\], 6, 2) = mid(\[event_datetime\], 6, 2) and mid(\[inclusion_arm_1\]\[dob\], 9, 2) \<= mid(\[event_datetime\], 9, 2)), 0, 1),"") | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| event_type | new_event | NA | radio | Neurovascular event | 1, TIA \| 2, AIS \| 3, ICH \| 4, SAH \| 99, Unknown | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
To save the metadata as labels in the dataset, we can save field labels
and the choices from radio buttons and dropdown features:
``` r
labelled_data <-
apply_field_label(
data = redcapcast_data,
meta = redcapcast_meta
) |>
apply_factor_labels(meta = redcapcast_meta)
```
The `REDCap_split` function splits the data set into a list of
data.frames.
``` r
list <-
REDCap_split(
records = labelled_data,
metadata = redcapcast_meta,
forms = "all"
) |>
# Next steps cleans up and removes generic columns
sanitize_split()
str(list)
#> List of 3
#> $ baseline_data_start: tibble [6 × 14] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:6] 1 2 3 4 5 6
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name : chr [1:6] "inclusion" "inclusion" "inclusion" "inclusion" ...
#> ..$ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> .. ..- attr(*, "label")= chr "CPR (Danish civil registration number)"
#> ..$ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> ..$ inclusion_time : 'hms' num [1:6] 12:38:49 10:38:57 12:01:07 20:39:19 ...
#> .. ..- attr(*, "units")= chr "secs"
#> ..$ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> ..$ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> .. ..- attr(*, "label")= chr "Age\r\nNote: Apparently, the build in datediff() function does not handle counting whole years. This results in"| __truncated__
#> ..$ age_integer : num [1:6] 83 89 66 117 126 91
#> .. ..- attr(*, "label")= chr "Age integer\r\nNote: as opposed to the build in datediff() this handles counting years as integers very well. C"| __truncated__
#> ..$ sex : chr [1:6] "female" "male" "male" "female" ...
#> .. ..- attr(*, "label")= chr "Legal sex"
#> ..$ cohabitation : 'labelled' chr [1:6] "Yes" "Yes" "No" NA ...
#> .. ..- attr(*, "label")= chr "Cohabitation"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ hypertension : 'labelled' chr [1:6] "No" "No" "Yes" NA ...
#> .. ..- attr(*, "label")= chr "Hypertension"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ diabetes : 'labelled' chr [1:6] "Yes" "No" "Yes" NA ...
#> .. ..- attr(*, "label")= chr "Diabetes"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ region : 'labelled' chr [1:6] "East" "South" "North" NA ...
#> .. ..- attr(*, "label")= chr "Region"
#> .. ..- attr(*, "labels")= Named chr [1:4] "1" "2" "3" "4"
#> .. .. ..- attr(*, "names")= chr [1:4] "North" "East" "South" "West"
#> ..$ baseline_data_start_complete: chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs : tibble [5 × 6] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:5] 1 2 2 3 3
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name: chr [1:5] "inclusion" "inclusion" "follow1" "follow1" ...
#> ..$ mrs_assessed : 'labelled' chr [1:5] "Yes" "Yes" "Yes" "Yes" ...
#> .. ..- attr(*, "label")= chr "Assesed"
#> .. ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> ..$ mrs_date : Date[1:5], format: "2023-03-13" "2023-03-07" ...
#> ..$ mrs_score : 'labelled' num [1:5] 1 1 3 2 1
#> .. ..- attr(*, "label")= chr "mRS score"
#> .. ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> ..$ mrs_complete : chr [1:5] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ new_event : tibble [13 × 8] (S3: tbl_df/tbl/data.frame)
#> ..$ record_id : num [1:13] 2 3 3 3 3 3 4 4 4 4 ...
#> .. ..- attr(*, "label")= chr "ID"
#> ..$ redcap_event_name : chr [1:13] "follow1" "follow1" "follow1" "follow2" ...
#> ..$ redcap_repeat_instrument: chr [1:13] "new_event" "new_event" "new_event" "new_event" ...
#> ..$ redcap_repeat_instance : num [1:13] 1 1 2 1 2 3 1 2 1 2 ...
#> ..$ event_datetime : POSIXct[1:13], format: "2024-01-18 12:49:42" "2024-01-18 12:49:58" ...
#> ..$ event_age : num [1:13] NA NA NA NA NA NA 96 105 118 118 ...
#> .. ..- attr(*, "label")= chr "Age at event"
#> ..$ event_type : 'labelled' chr [1:13] "TIA" "AIS" "ICH" "ICH" ...
#> .. ..- attr(*, "label")= chr "Neurovascular event"
#> .. ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> ..$ new_event_complete : chr [1:13] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
```
The
[`easy_redcap()`](https://agdamsbo.github.io/REDCapCAST/reference/easy_redcap.md)
will then (optionally) continue to widen the data, by transforming the
list of data.frames to a single data.frame with one row for each
subject/record_id (wide data format):
``` r
wide_data <- redcap_wider(list,
event.glue = "{.value}____{redcap_event_name}",
inst.glue = "{.value}____{redcap_repeat_instance}"
)
#> Joining with `by = join_by(record_id)`
#> Joining with `by = join_by(record_id)`
wide_data |> str()
#> tibble [6 × 49] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:6] 1 2 3 4 5 6
#> ..- attr(*, "label")= chr "ID"
#> $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> ..- attr(*, "label")= chr "CPR (Danish civil registration number)"
#> $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:6] 12:38:49 10:38:57 12:01:07 20:39:19 ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> ..- attr(*, "label")= chr "Age\r\nNote: Apparently, the build in datediff() function does not handle counting whole years. This results in"| __truncated__
#> $ age_integer : num [1:6] 83 89 66 117 126 91
#> ..- attr(*, "label")= chr "Age integer\r\nNote: as opposed to the build in datediff() this handles counting years as integers very well. C"| __truncated__
#> $ sex : chr [1:6] "female" "male" "male" "female" ...
#> ..- attr(*, "label")= chr "Legal sex"
#> $ cohabitation : 'labelled' chr [1:6] "Yes" "Yes" "No" NA ...
#> ..- attr(*, "label")= chr "Cohabitation"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ hypertension : 'labelled' chr [1:6] "No" "No" "Yes" NA ...
#> ..- attr(*, "label")= chr "Hypertension"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ diabetes : 'labelled' chr [1:6] "Yes" "No" "Yes" NA ...
#> ..- attr(*, "label")= chr "Diabetes"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ region : 'labelled' chr [1:6] "East" "South" "North" NA ...
#> ..- attr(*, "label")= chr "Region"
#> ..- attr(*, "labels")= Named chr [1:4] "1" "2" "3" "4"
#> .. ..- attr(*, "names")= chr [1:4] "North" "East" "South" "West"
#> $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs_assessed____inclusion : 'labelled' chr [1:6] "Yes" "Yes" NA NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_assessed____follow1 : 'labelled' chr [1:6] NA "Yes" "Yes" NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_assessed____follow2 : 'labelled' chr [1:6] NA NA "Yes" NA ...
#> ..- attr(*, "label")= chr "Assesed"
#> ..- attr(*, "labels")= Named chr [1:2] "1" "2"
#> .. ..- attr(*, "names")= chr [1:2] "Yes" "No"
#> $ mrs_date____inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_date____follow1 : Date[1:6], format: NA "2023-03-09" ...
#> $ mrs_date____follow2 : Date[1:6], format: NA NA ...
#> $ mrs_score____inclusion : 'labelled' num [1:6] 1 1 NA NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_score____follow1 : 'labelled' num [1:6] NA 3 2 NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_score____follow2 : 'labelled' num [1:6] NA NA 1 NA NA NA
#> ..- attr(*, "label")= chr "mRS score"
#> ..- attr(*, "labels")= Named chr [1:6] "0" "1" "2" "3" ...
#> .. ..- attr(*, "names")= chr [1:6] "0" "1" "2" "3" ...
#> $ mrs_complete____inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_complete____follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...
#> $ mrs_complete____follow2 : chr [1:6] NA NA "Incomplete" NA ...
#> $ event_datetime____1____follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...
#> $ event_datetime____1____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____1____follow1 : num [1:6] NA NA NA 96 127 NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____1____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_type____1____follow1 : 'labelled' chr [1:6] NA "TIA" "AIS" "TIA" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____1____follow2 : 'labelled' chr [1:6] NA NA "ICH" "AIS" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ new_event_complete____1____follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...
#> $ new_event_complete____1____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ event_datetime____2____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____2____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____2____follow1 : num [1:6] NA NA NA 105 127 NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____2____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____3____follow1 : num [1:6] NA NA NA NA NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_age____3____follow2 : num [1:6] NA NA NA 118 NA NA
#> ..- attr(*, "label")= chr "Age at event"
#> $ event_type____2____follow1 : 'labelled' chr [1:6] NA NA "ICH" "TIA" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____2____follow2 : 'labelled' chr [1:6] NA NA "TIA" "ICH" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____3____follow1 : 'labelled' chr [1:6] NA NA NA NA ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ event_type____3____follow2 : 'labelled' chr [1:6] NA NA "AIS" "Unknown" ...
#> ..- attr(*, "label")= chr "Neurovascular event"
#> ..- attr(*, "labels")= Named chr [1:5] "1" "2" "3" "4" ...
#> .. ..- attr(*, "names")= chr [1:5] "TIA" "AIS" "ICH" "SAH" ...
#> $ new_event_complete____2____follow1: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ new_event_complete____2____follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...
#> $ new_event_complete____3____follow1: chr [1:6] NA NA NA NA ...
#> $ new_event_complete____3____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
```
Transfer suffixes to labels:
``` r
wide_data_suffixes <- wide_data |> suffix2label()
```
## Creating a nice table
``` r
wide_data_suffixes |>
as_factor()|>
dplyr::select(sex, hypertension, diabetes,mrs_score____follow2) |>
gtsummary::tbl_summary(type = gtsummary::all_dichotomous() ~ "categorical")
```
[TABLE]

View file

@ -1,17 +1,16 @@
<!DOCTYPE html>
<!-- Generated by pkgdown: do not edit by hand --><html lang="en">
<!-- Generated by pkgdown: do not edit by hand --><html lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Shiny-app • REDCapCAST</title>
<!-- favicons --><link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="../favicon-32x32.png">
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="../apple-touch-icon.png">
<link rel="apple-touch-icon" type="image/png" sizes="120x120" href="../apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" type="image/png" sizes="76x76" href="../apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" type="image/png" sizes="60x60" href="../apple-touch-icon-60x60.png">
<!-- favicons --><link rel="icon" type="image/png" sizes="96x96" href="../favicon-96x96.png">
<link rel="icon" type="”image/svg+xml”" href="../favicon.svg">
<link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon.png">
<link rel="icon" sizes="any" href="../favicon.ico">
<link rel="manifest" href="../site.webmanifest">
<script src="../deps/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="../deps/bootstrap-5.3.1/bootstrap.min.css" rel="stylesheet">
<script src="../deps/bootstrap-5.3.1/bootstrap.bundle.min.js"></script><link href="../deps/font-awesome-6.5.2/css/all.min.css" rel="stylesheet">
@ -26,7 +25,7 @@
<a class="navbar-brand me-2" href="../index.html">REDCapCAST</a>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.3.2</small>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.11.1</small>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
@ -67,7 +66,7 @@
<h1>Shiny-app</h1>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/v25.3.2/vignettes/Shiny-app.Rmd" class="external-link"><code>vignettes/Shiny-app.Rmd</code></a></small>
<small class="dont-index">Source: <a href="https://github.com/agdamsbo/REDCapCAST/blob/main/vignettes/Shiny-app.Rmd" class="external-link"><code>vignettes/Shiny-app.Rmd</code></a></small>
<div class="d-none name"><code>Shiny-app.Rmd</code></div>
</div>
@ -151,55 +150,55 @@ and launch the app as follows:</p>
<span> <span class="fu">purrr</span><span class="fu">::</span><span class="fu"><a href="https://purrr.tidyverse.org/reference/pluck.html" class="external-link">pluck</a></span><span class="op">(</span><span class="st">"data"</span><span class="op">)</span> <span class="op">|&gt;</span> </span>
<span> <span class="fu"><a href="https://rdrr.io/r/utils/str.html" class="external-link">str</a></span><span class="op">(</span><span class="op">)</span></span>
<span><span class="co">#&gt; tibble [6 × 49] (S3: tbl_df/tbl/data.frame)</span></span>
<span><span class="co">#&gt; $ record_id : num [1:6] 1 2 3 4 5 6</span></span>
<span><span class="co">#&gt; $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...</span></span>
<span><span class="co">#&gt; $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...</span></span>
<span><span class="co">#&gt; $ inclusion_time : chr [1:6] "12:38:49" "10:38:57" "12:01:07" "20:39:19" ...</span></span>
<span><span class="co">#&gt; $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...</span></span>
<span><span class="co">#&gt; $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...</span></span>
<span><span class="co">#&gt; $ age_integer : num [1:6] 83 89 66 117 126 91</span></span>
<span><span class="co">#&gt; $ sex : chr [1:6] "female" "male" "male" "female" ...</span></span>
<span><span class="co">#&gt; $ cohabitation : chr [1:6] "Yes" "Yes" "No" NA ...</span></span>
<span><span class="co">#&gt; $ hypertension : chr [1:6] "No" "No" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ diabetes : chr [1:6] "Yes" "No" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ region : chr [1:6] "East" "South" "North" NA ...</span></span>
<span><span class="co">#&gt; $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed____inclusion : chr [1:6] "Yes" "Yes" NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed____follow1 : chr [1:6] NA "Yes" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed____follow2 : chr [1:6] NA NA "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_date____inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...</span></span>
<span><span class="co">#&gt; $ mrs_date____follow1 : Date[1:6], format: NA "2023-03-09" ...</span></span>
<span><span class="co">#&gt; $ mrs_date____follow2 : Date[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_score____inclusion : num [1:6] 1 1 NA NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_score____follow1 : num [1:6] NA 3 2 NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_score____follow2 : num [1:6] NA NA 1 NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_complete____inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_complete____follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_complete____follow2 : chr [1:6] NA NA "Incomplete" NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime____1____follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...</span></span>
<span><span class="co">#&gt; $ event_datetime____1____follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_age____1____follow1 : num [1:6] NA NA NA 96 127 NA</span></span>
<span><span class="co">#&gt; $ event_age____1____follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_type____1____follow1 : chr [1:6] NA "TIA" "AIS" "TIA" ...</span></span>
<span><span class="co">#&gt; $ event_type____1____follow2 : chr [1:6] NA NA "ICH" "AIS" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____1____follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____1____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ event_datetime____2____follow1 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime____2____follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime____3____follow1 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime____3____follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_age____2____follow1 : num [1:6] NA NA NA 105 127 NA</span></span>
<span><span class="co">#&gt; $ event_age____2____follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_age____3____follow1 : num [1:6] NA NA NA NA NA NA</span></span>
<span><span class="co">#&gt; $ event_age____3____follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_type____2____follow1 : chr [1:6] NA NA "ICH" "TIA" ...</span></span>
<span><span class="co">#&gt; $ event_type____2____follow2 : chr [1:6] NA NA "TIA" "ICH" ...</span></span>
<span><span class="co">#&gt; $ event_type____3____follow1 : chr [1:6] NA NA NA NA ...</span></span>
<span><span class="co">#&gt; $ event_type____3____follow2 : chr [1:6] NA NA "AIS" "Unknown" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____2____follow1: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____2____follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____3____follow1: chr [1:6] NA NA NA NA ...</span></span>
<span><span class="co">#&gt; $ new_event_complete____3____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span></code></pre></div>
<span><span class="co">#&gt; $ record_id : num [1:6] 1 2 3 4 5 6</span></span>
<span><span class="co">#&gt; $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...</span></span>
<span><span class="co">#&gt; $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...</span></span>
<span><span class="co">#&gt; $ inclusion_time : chr [1:6] "12:38:49" "10:38:57" "12:01:07" "20:39:19" ...</span></span>
<span><span class="co">#&gt; $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...</span></span>
<span><span class="co">#&gt; $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...</span></span>
<span><span class="co">#&gt; $ age_integer : num [1:6] 83 89 66 117 126 91</span></span>
<span><span class="co">#&gt; $ sex : chr [1:6] "female" "male" "male" "female" ...</span></span>
<span><span class="co">#&gt; $ cohabitation : chr [1:6] "Yes" "Yes" "No" NA ...</span></span>
<span><span class="co">#&gt; $ hypertension : chr [1:6] "No" "No" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ diabetes : chr [1:6] "Yes" "No" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ region : chr [1:6] "East" "South" "North" NA ...</span></span>
<span><span class="co">#&gt; $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed__inclusion : chr [1:6] "Yes" "Yes" NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed__follow1 : chr [1:6] NA "Yes" "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_assessed__follow2 : chr [1:6] NA NA "Yes" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_date__inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...</span></span>
<span><span class="co">#&gt; $ mrs_date__follow1 : Date[1:6], format: NA "2023-03-09" ...</span></span>
<span><span class="co">#&gt; $ mrs_date__follow2 : Date[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_score__inclusion : num [1:6] 1 1 NA NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_score__follow1 : num [1:6] NA 3 2 NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_score__follow2 : num [1:6] NA NA 1 NA NA NA</span></span>
<span><span class="co">#&gt; $ mrs_complete__inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...</span></span>
<span><span class="co">#&gt; $ mrs_complete__follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...</span></span>
<span><span class="co">#&gt; $ mrs_complete__follow2 : chr [1:6] NA NA "Incomplete" NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime__1__follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...</span></span>
<span><span class="co">#&gt; $ event_datetime__1__follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_age__1__follow1 : num [1:6] NA NA NA 96 127 NA</span></span>
<span><span class="co">#&gt; $ event_age__1__follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_type__1__follow1 : chr [1:6] NA "TIA" "AIS" "TIA" ...</span></span>
<span><span class="co">#&gt; $ event_type__1__follow2 : chr [1:6] NA NA "ICH" "AIS" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__1__follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__1__follow2: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ event_datetime__2__follow1 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime__2__follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime__3__follow1 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_datetime__3__follow2 : POSIXct[1:6], format: NA NA ...</span></span>
<span><span class="co">#&gt; $ event_age__2__follow1 : num [1:6] NA NA NA 105 127 NA</span></span>
<span><span class="co">#&gt; $ event_age__2__follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_age__3__follow1 : num [1:6] NA NA NA NA NA NA</span></span>
<span><span class="co">#&gt; $ event_age__3__follow2 : num [1:6] NA NA NA 118 NA NA</span></span>
<span><span class="co">#&gt; $ event_type__2__follow1 : chr [1:6] NA NA "ICH" "TIA" ...</span></span>
<span><span class="co">#&gt; $ event_type__2__follow2 : chr [1:6] NA NA "TIA" "ICH" ...</span></span>
<span><span class="co">#&gt; $ event_type__3__follow1 : chr [1:6] NA NA NA NA ...</span></span>
<span><span class="co">#&gt; $ event_type__3__follow2 : chr [1:6] NA NA "AIS" "Unknown" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__2__follow1: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__2__follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__3__follow1: chr [1:6] NA NA NA NA ...</span></span>
<span><span class="co">#&gt; $ new_event_complete__3__follow2: chr [1:6] NA NA "Incomplete" "Complete" ...</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="downlit sourceCode r">
<code class="sourceCode R"><span><span class="va">ds</span><span class="op">|&gt;</span> </span>
<span> <span class="fu"><a href="../reference/ds2dd_detailed.html">ds2dd_detailed</a></span><span class="op">(</span>metadata <span class="op">=</span> <span class="fu"><a href="https://rdrr.io/r/base/names.html" class="external-link">names</a></span><span class="op">(</span><span class="fu">REDCapCAST</span><span class="fu">::</span><span class="va"><a href="../reference/redcapcast_meta.html">redcapcast_meta</a></span><span class="op">)</span><span class="op">)</span><span class="op">|&gt;</span> </span>
@ -379,7 +378,7 @@ based on a set threshold for unique values:</p>
</div>
<div class="pkgdown-footer-right">
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.1.1.</p>
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.2.0.</p>
</div>
</footer>

323
articles/Shiny-app.md Normal file
View file

@ -0,0 +1,323 @@
# Shiny-app
To make the easiest possible transition from spreadsheet/dataset to
REDCap, I have created a small app, which adds a graphical interface to
the casting of a data dictionary and data upload. Install the package
and launch the app as follows:
``` r
REDCapCAST::shiny_cast()
```
The app primarily wraps one function:
[`ds2dd_detailed()`](https://agdamsbo.github.io/REDCapCAST/reference/ds2dd_detailed.md).
``` r
library(REDCapCAST)
ds <- REDCap_split(
records = redcapcast_data,
metadata = redcapcast_meta,
forms = "all"
) |>
sanitize_split() |>
redcap_wider()
#> Joining with `by = join_by(record_id)`
#> Joining with `by = join_by(record_id)`
str(ds)
#> tibble [6 × 49] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:6] 1 2 3 4 5 6
#> $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:6] 12:38:49 10:38:57 12:01:07 20:39:19 ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> $ age_integer : num [1:6] 83 89 66 117 126 91
#> $ sex : chr [1:6] "female" "male" "male" "female" ...
#> $ cohabitation : chr [1:6] "Yes" "Yes" "No" NA ...
#> $ hypertension : chr [1:6] "No" "No" "Yes" NA ...
#> $ diabetes : chr [1:6] "Yes" "No" "Yes" NA ...
#> $ region : chr [1:6] "East" "South" "North" NA ...
#> $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs_assessed____inclusion : chr [1:6] "Yes" "Yes" NA NA ...
#> $ mrs_assessed____follow1 : chr [1:6] NA "Yes" "Yes" NA ...
#> $ mrs_assessed____follow2 : chr [1:6] NA NA "Yes" NA ...
#> $ mrs_date____inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_date____follow1 : Date[1:6], format: NA "2023-03-09" ...
#> $ mrs_date____follow2 : Date[1:6], format: NA NA ...
#> $ mrs_score____inclusion : num [1:6] 1 1 NA NA NA NA
#> $ mrs_score____follow1 : num [1:6] NA 3 2 NA NA NA
#> $ mrs_score____follow2 : num [1:6] NA NA 1 NA NA NA
#> $ mrs_complete____inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_complete____follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...
#> $ mrs_complete____follow2 : chr [1:6] NA NA "Incomplete" NA ...
#> $ event_datetime____1____follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...
#> $ event_datetime____1____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____1____follow1 : num [1:6] NA NA NA 96 127 NA
#> $ event_age____1____follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_type____1____follow1 : chr [1:6] NA "TIA" "AIS" "TIA" ...
#> $ event_type____1____follow2 : chr [1:6] NA NA "ICH" "AIS" ...
#> $ new_event_complete____1____follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...
#> $ new_event_complete____1____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ event_datetime____2____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____2____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime____3____follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age____2____follow1 : num [1:6] NA NA NA 105 127 NA
#> $ event_age____2____follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_age____3____follow1 : num [1:6] NA NA NA NA NA NA
#> $ event_age____3____follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_type____2____follow1 : chr [1:6] NA NA "ICH" "TIA" ...
#> $ event_type____2____follow2 : chr [1:6] NA NA "TIA" "ICH" ...
#> $ event_type____3____follow1 : chr [1:6] NA NA NA NA ...
#> $ event_type____3____follow2 : chr [1:6] NA NA "AIS" "Unknown" ...
#> $ new_event_complete____2____follow1: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ new_event_complete____2____follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...
#> $ new_event_complete____3____follow1: chr [1:6] NA NA NA NA ...
#> $ new_event_complete____3____follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
#> - attr(*, "problems")=<externalptr>
```
``` r
ds|>
ds2dd_detailed(metadata = names(REDCapCAST::redcapcast_meta))|>
purrr::pluck("data") |>
str()
#> tibble [6 × 49] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:6] 1 2 3 4 5 6
#> $ cpr : chr [1:6] "1203401OB4" "0102342303" "2301569823" "0204051342" ...
#> $ inclusion : Date[1:6], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : chr [1:6] "12:38:49" "10:38:57" "12:01:07" "20:39:19" ...
#> $ dob : Date[1:6], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:6] 83 89.1 66.1 117.9 126.2 ...
#> $ age_integer : num [1:6] 83 89 66 117 126 91
#> $ sex : chr [1:6] "female" "male" "male" "female" ...
#> $ cohabitation : chr [1:6] "Yes" "Yes" "No" NA ...
#> $ hypertension : chr [1:6] "No" "No" "Yes" NA ...
#> $ diabetes : chr [1:6] "Yes" "No" "Yes" NA ...
#> $ region : chr [1:6] "East" "South" "North" NA ...
#> $ baseline_data_start_complete : chr [1:6] "Incomplete" "Incomplete" "Incomplete" "Incomplete" ...
#> $ mrs_assessed__inclusion : chr [1:6] "Yes" "Yes" NA NA ...
#> $ mrs_assessed__follow1 : chr [1:6] NA "Yes" "Yes" NA ...
#> $ mrs_assessed__follow2 : chr [1:6] NA NA "Yes" NA ...
#> $ mrs_date__inclusion : Date[1:6], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_date__follow1 : Date[1:6], format: NA "2023-03-09" ...
#> $ mrs_date__follow2 : Date[1:6], format: NA NA ...
#> $ mrs_score__inclusion : num [1:6] 1 1 NA NA NA NA
#> $ mrs_score__follow1 : num [1:6] NA 3 2 NA NA NA
#> $ mrs_score__follow2 : num [1:6] NA NA 1 NA NA NA
#> $ mrs_complete__inclusion : chr [1:6] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_complete__follow1 : chr [1:6] NA "Incomplete" "Incomplete" NA ...
#> $ mrs_complete__follow2 : chr [1:6] NA NA "Incomplete" NA ...
#> $ event_datetime__1__follow1 : POSIXct[1:6], format: NA "2024-01-18 12:49:42" ...
#> $ event_datetime__1__follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age__1__follow1 : num [1:6] NA NA NA 96 127 NA
#> $ event_age__1__follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_type__1__follow1 : chr [1:6] NA "TIA" "AIS" "TIA" ...
#> $ event_type__1__follow2 : chr [1:6] NA NA "ICH" "AIS" ...
#> $ new_event_complete__1__follow1: chr [1:6] NA "Incomplete" "Incomplete" "Complete" ...
#> $ new_event_complete__1__follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ event_datetime__2__follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime__2__follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime__3__follow1 : POSIXct[1:6], format: NA NA ...
#> $ event_datetime__3__follow2 : POSIXct[1:6], format: NA NA ...
#> $ event_age__2__follow1 : num [1:6] NA NA NA 105 127 NA
#> $ event_age__2__follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_age__3__follow1 : num [1:6] NA NA NA NA NA NA
#> $ event_age__3__follow2 : num [1:6] NA NA NA 118 NA NA
#> $ event_type__2__follow1 : chr [1:6] NA NA "ICH" "TIA" ...
#> $ event_type__2__follow2 : chr [1:6] NA NA "TIA" "ICH" ...
#> $ event_type__3__follow1 : chr [1:6] NA NA NA NA ...
#> $ event_type__3__follow2 : chr [1:6] NA NA "AIS" "Unknown" ...
#> $ new_event_complete__2__follow1: chr [1:6] NA NA "Incomplete" "Complete" ...
#> $ new_event_complete__2__follow2: chr [1:6] NA NA "Incomplete" "Incomplete" ...
#> $ new_event_complete__3__follow1: chr [1:6] NA NA NA NA ...
#> $ new_event_complete__3__follow2: chr [1:6] NA NA "Incomplete" "Complete" ...
```
``` r
ds|>
ds2dd_detailed(metadata = names(REDCapCAST::redcapcast_meta))|>
purrr::pluck("meta") |>
head(10)
#> # A tibble: 10 × 18
#> field_name form_name section_header field_type field_label
#> <chr> <chr> <lgl> <chr> <chr>
#> 1 record_id data NA text record_id
#> 2 cpr data NA text cpr
#> 3 inclusion data NA text inclusion
#> 4 inclusion_time data NA text inclusion_time
#> 5 dob data NA text dob
#> 6 age data NA text age
#> 7 age_integer data NA text age_integer
#> 8 sex data NA text sex
#> 9 cohabitation data NA text cohabitation
#> 10 hypertension data NA text hypertension
#> # 13 more variables: select_choices_or_calculations <lgl>, field_note <lgl>,
#> # text_validation_type_or_show_slider_number <chr>,
#> # text_validation_min <lgl>, text_validation_max <lgl>, identifier <lgl>,
#> # branching_logic <lgl>, required_field <lgl>, custom_alignment <lgl>,
#> # question_number <lgl>, matrix_group_name <lgl>, matrix_ranking <lgl>,
#> # field_annotation <lgl>
```
Different data formats are accepted, which all mostly implements the
[`readr::col_guess()`](https://readr.tidyverse.org/reference/parse_guess.html)
functionality to parse column classes.
To ensure uniformity in data import this parsing has been implemented on
its own to use with
[`ds2dd_detailed()`](https://agdamsbo.github.io/REDCapCAST/reference/ds2dd_detailed.md)
or any other data set for that matter:
``` r
ds_parsed <- redcapcast_data |>
dplyr::mutate(dplyr::across(dplyr::everything(),as.character)) |>
parse_data()
str(ds_parsed)
#> tibble [25 × 27] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:25] 1 2 2 2 3 3 3 3 3 3 ...
#> $ redcap_event_name : chr [1:25] "inclusion" "inclusion" "follow1" "follow1" ...
#> $ redcap_repeat_instrument : chr [1:25] NA NA NA "New Event (?)" ...
#> $ redcap_repeat_instance : num [1:25] NA NA NA 1 NA NA NA 1 2 1 ...
#> $ cpr : chr [1:25] "1203401OB4" "0102342303" NA NA ...
#> $ inclusion : Date[1:25], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:25] 12:38:49 10:38:57 NA NA ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:25], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:25] 83 89.1 NA NA 66.1 ...
#> $ age_integer : num [1:25] 83 89 NA NA 66 NA NA NA NA NA ...
#> $ sex : chr [1:25] "female" "male" NA NA ...
#> $ cohabitation : chr [1:25] "Yes" "Yes" NA NA ...
#> $ hypertension : chr [1:25] "No" "No" NA NA ...
#> $ diabetes : chr [1:25] "Yes" "No" NA NA ...
#> $ region : chr [1:25] "East" "South" NA NA ...
#> $ baseline_data_start_complete: chr [1:25] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_assessed : chr [1:25] "Yes" "Yes" "Yes" NA ...
#> $ mrs_date : Date[1:25], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_score : num [1:25] 1 1 3 NA NA 2 1 NA NA NA ...
#> $ mrs_complete : chr [1:25] "Incomplete" "Incomplete" "Incomplete" NA ...
#> $ con_mrs : logi [1:25] NA NA NA NA NA NA ...
#> $ con_calc : logi [1:25] NA NA NA NA NA NA ...
#> $ consensus_complete : chr [1:25] NA NA "Incomplete" NA ...
#> $ event_datetime : POSIXct[1:25], format: NA NA ...
#> $ event_age : num [1:25] NA NA NA NA NA NA NA NA NA NA ...
#> $ event_type : chr [1:25] NA NA NA "TIA" ...
#> $ new_event_complete : chr [1:25] NA NA NA "Incomplete" ...
#> - attr(*, "problems")=<externalptr>
```
It will ignore specified columns, which is neat for numeric-looking
strings like cpr-with a leading 0:
``` r
redcapcast_data |>
dplyr::mutate(dplyr::across(dplyr::everything(),as.character)) |>
parse_data(ignore.vars = c("record_id","cpr")) |>
str()
#> tibble [25 × 27] (S3: tbl_df/tbl/data.frame)
#> $ record_id : chr [1:25] "1" "2" "2" "2" ...
#> $ redcap_event_name : chr [1:25] "inclusion" "inclusion" "follow1" "follow1" ...
#> $ redcap_repeat_instrument : chr [1:25] NA NA NA "New Event (?)" ...
#> $ redcap_repeat_instance : num [1:25] NA NA NA 1 NA NA NA 1 2 1 ...
#> $ cpr : chr [1:25] "1203401OB4" "0102342303" NA NA ...
#> $ inclusion : Date[1:25], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:25] 12:38:49 10:38:57 NA NA ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:25], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:25] 83 89.1 NA NA 66.1 ...
#> $ age_integer : num [1:25] 83 89 NA NA 66 NA NA NA NA NA ...
#> $ sex : chr [1:25] "female" "male" NA NA ...
#> $ cohabitation : chr [1:25] "Yes" "Yes" NA NA ...
#> $ hypertension : chr [1:25] "No" "No" NA NA ...
#> $ diabetes : chr [1:25] "Yes" "No" NA NA ...
#> $ region : chr [1:25] "East" "South" NA NA ...
#> $ baseline_data_start_complete: chr [1:25] "Incomplete" "Incomplete" NA NA ...
#> $ mrs_assessed : chr [1:25] "Yes" "Yes" "Yes" NA ...
#> $ mrs_date : Date[1:25], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_score : num [1:25] 1 1 3 NA NA 2 1 NA NA NA ...
#> $ mrs_complete : chr [1:25] "Incomplete" "Incomplete" "Incomplete" NA ...
#> $ con_mrs : logi [1:25] NA NA NA NA NA NA ...
#> $ con_calc : logi [1:25] NA NA NA NA NA NA ...
#> $ consensus_complete : chr [1:25] NA NA "Incomplete" NA ...
#> $ event_datetime : POSIXct[1:25], format: NA NA ...
#> $ event_age : num [1:25] NA NA NA NA NA NA NA NA NA NA ...
#> $ event_type : chr [1:25] NA NA NA "TIA" ...
#> $ new_event_complete : chr [1:25] NA NA NA "Incomplete" ...
#> - attr(*, "problems")=<externalptr>
```
Column classes can be passed to
[`parse_data()`](https://agdamsbo.github.io/REDCapCAST/reference/parse_data.md).
Making a few crude assumption for factorising data,
[`numchar2fct()`](https://agdamsbo.github.io/REDCapCAST/reference/numchar2fct.md)
factorises numerical and character vectors based on a set threshold for
unique values:
``` r
mtcars |> str()
#> 'data.frame': 32 obs. of 11 variables:
#> $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#> $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
#> $ disp: num 160 160 108 258 360 ...
#> $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
#> $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#> $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
#> $ qsec: num 16.5 17 18.6 19.4 17 ...
#> $ vs : num 0 0 1 1 0 1 0 1 1 1 ...
#> $ am : num 1 1 1 0 0 0 0 0 0 0 ...
#> $ gear: num 4 4 4 3 3 3 3 4 4 4 ...
#> $ carb: num 4 4 1 1 2 1 4 2 2 4 ...
mtcars |>
numchar2fct(numeric.threshold = 6) |>
str()
#> 'data.frame': 32 obs. of 11 variables:
#> $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#> $ cyl : Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1 1 2 ...
#> $ disp: num 160 160 108 258 360 ...
#> $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
#> $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#> $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
#> $ qsec: num 16.5 17 18.6 19.4 17 ...
#> $ vs : Factor w/ 2 levels "0","1": 1 1 2 2 1 2 1 2 2 2 ...
#> $ am : Factor w/ 2 levels "0","1": 2 2 2 1 1 1 1 1 1 1 ...
#> $ gear: Factor w/ 3 levels "3","4","5": 2 2 2 1 1 1 1 2 2 2 ...
#> $ carb: Factor w/ 6 levels "1","2","3","4",..: 4 4 1 1 2 1 4 2 2 4 ...
```
``` r
ds_parsed|>
numchar2fct(numeric.threshold = 2) |>
str()
#> tibble [25 × 27] (S3: tbl_df/tbl/data.frame)
#> $ record_id : num [1:25] 1 2 2 2 3 3 3 3 3 3 ...
#> $ redcap_event_name : Factor w/ 3 levels "inclusion","follow1",..: 1 1 2 2 1 2 3 2 2 3 ...
#> $ redcap_repeat_instrument : Factor w/ 1 level "New Event (?)": NA NA NA 1 NA NA NA 1 1 1 ...
#> $ redcap_repeat_instance : num [1:25] NA NA NA 1 NA NA NA 1 2 1 ...
#> $ cpr : chr [1:25] "1203401OB4" "0102342303" NA NA ...
#> $ inclusion : Date[1:25], format: "2023-03-13" "2023-03-01" ...
#> $ inclusion_time : 'hms' num [1:25] 12:38:49 10:38:57 NA NA ...
#> ..- attr(*, "units")= chr "secs"
#> $ dob : Date[1:25], format: "1940-03-12" "1934-02-01" ...
#> $ age : num [1:25] 83 89.1 NA NA 66.1 ...
#> $ age_integer : num [1:25] 83 89 NA NA 66 NA NA NA NA NA ...
#> $ sex : Factor w/ 2 levels "female","male": 1 2 NA NA 2 NA NA NA NA NA ...
#> $ cohabitation : Factor w/ 2 levels "Yes","No": 1 1 NA NA 2 NA NA NA NA NA ...
#> $ hypertension : Factor w/ 2 levels "No","Yes": 1 1 NA NA 2 NA NA NA NA NA ...
#> $ diabetes : Factor w/ 2 levels "Yes","No": 1 2 NA NA 1 NA NA NA NA NA ...
#> $ region : Factor w/ 3 levels "East","South",..: 1 2 NA NA 3 NA NA NA NA NA ...
#> $ baseline_data_start_complete: Factor w/ 2 levels "Incomplete","Complete": 1 1 NA NA 1 NA NA NA NA NA ...
#> $ mrs_assessed : Factor w/ 1 level "Yes": 1 1 1 NA NA 1 1 NA NA NA ...
#> $ mrs_date : Date[1:25], format: "2023-03-13" "2023-03-07" ...
#> $ mrs_score : num [1:25] 1 1 3 NA NA 2 1 NA NA NA ...
#> $ mrs_complete : Factor w/ 1 level "Incomplete": 1 1 1 NA 1 1 1 NA NA NA ...
#> $ con_mrs : logi [1:25] NA NA NA NA NA NA ...
#> $ con_calc : logi [1:25] NA NA NA NA NA NA ...
#> $ consensus_complete : Factor w/ 1 level "Incomplete": NA NA 1 NA NA 1 1 NA NA NA ...
#> $ event_datetime : POSIXct[1:25], format: NA NA ...
#> $ event_age : num [1:25] NA NA NA NA NA NA NA NA NA NA ...
#> $ event_type : Factor w/ 4 levels "TIA","AIS","ICH",..: NA NA NA 1 NA NA NA 2 3 3 ...
#> $ new_event_complete : Factor w/ 2 levels "Incomplete","Complete": NA NA NA 1 NA NA NA 1 1 1 ...
#> - attr(*, "problems")=<externalptr>
```

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- Generated by pkgdown: do not edit by hand --><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><title>Articles • REDCapCAST</title><!-- favicons --><link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="../favicon-32x32.png"><link rel="apple-touch-icon" type="image/png" sizes="180x180" href="../apple-touch-icon.png"><link rel="apple-touch-icon" type="image/png" sizes="120x120" href="../apple-touch-icon-120x120.png"><link rel="apple-touch-icon" type="image/png" sizes="76x76" href="../apple-touch-icon-76x76.png"><link rel="apple-touch-icon" type="image/png" sizes="60x60" href="../apple-touch-icon-60x60.png"><script src="../deps/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link href="../deps/bootstrap-5.3.1/bootstrap.min.css" rel="stylesheet"><script src="../deps/bootstrap-5.3.1/bootstrap.bundle.min.js"></script><link href="../deps/font-awesome-6.5.2/css/all.min.css" rel="stylesheet"><link href="../deps/font-awesome-6.5.2/css/v4-shims.min.css" rel="stylesheet"><script src="../deps/headroom-0.11.0/headroom.min.js"></script><script src="../deps/headroom-0.11.0/jQuery.headroom.min.js"></script><script src="../deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js"></script><script src="../deps/clipboard.js-2.0.11/clipboard.min.js"></script><script src="../deps/search-1.0.0/autocomplete.jquery.min.js"></script><script src="../deps/search-1.0.0/fuse.min.js"></script><script src="../deps/search-1.0.0/mark.min.js"></script><!-- pkgdown --><script src="../pkgdown.js"></script><meta property="og:title" content="Articles"></head><body>
<!-- Generated by pkgdown: do not edit by hand --><html lang="en-US"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><title>Articles • REDCapCAST</title><!-- favicons --><link rel="icon" type="image/png" sizes="96x96" href="../favicon-96x96.png"><link rel="icon" type="”image/svg+xml”" href="../favicon.svg"><link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon.png"><link rel="icon" sizes="any" href="../favicon.ico"><link rel="manifest" href="../site.webmanifest"><script src="../deps/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link href="../deps/bootstrap-5.3.1/bootstrap.min.css" rel="stylesheet"><script src="../deps/bootstrap-5.3.1/bootstrap.bundle.min.js"></script><link href="../deps/font-awesome-6.5.2/css/all.min.css" rel="stylesheet"><link href="../deps/font-awesome-6.5.2/css/v4-shims.min.css" rel="stylesheet"><script src="../deps/headroom-0.11.0/headroom.min.js"></script><script src="../deps/headroom-0.11.0/jQuery.headroom.min.js"></script><script src="../deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js"></script><script src="../deps/clipboard.js-2.0.11/clipboard.min.js"></script><script src="../deps/search-1.0.0/autocomplete.jquery.min.js"></script><script src="../deps/search-1.0.0/fuse.min.js"></script><script src="../deps/search-1.0.0/mark.min.js"></script><!-- pkgdown --><script src="../pkgdown.js"></script><meta property="og:title" content="Articles"></head><body>
<a href="#main" class="visually-hidden-focusable">Skip to contents</a>
@ -7,7 +7,7 @@
<a class="navbar-brand me-2" href="../index.html">REDCapCAST</a>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.3.2</small>
<small class="nav-text text-muted me-auto" data-bs-toggle="tooltip" data-bs-placement="bottom" title="">25.11.1</small>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
@ -56,7 +56,7 @@
</div>
<div class="pkgdown-footer-right">
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.1.1.</p>
<p>Site built with <a href="https://pkgdown.r-lib.org/" class="external-link">pkgdown</a> 2.2.0.</p>
</div>
</footer></div>

7
articles/index.md Normal file
View file

@ -0,0 +1,7 @@
# Articles
### All vignettes
- [Database-creation](https://agdamsbo.github.io/REDCapCAST/articles/Database-creation.md):
- [REDCapCAST](https://agdamsbo.github.io/REDCapCAST/articles/REDCapCAST.md):
- [Shiny-app](https://agdamsbo.github.io/REDCapCAST/articles/Shiny-app.md):