Skip to content

Commit 3221e3a

Browse files
Closes #96 blog post on admiral 1.0.0 (#100)
* feat: #96 image and skeleton * feat: new functions section started * feat: onboarding resources * feat: #96 finishing ef_msrc section * feat: #96 finished function section. working on bug and argument section * feat: #96 stability section * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * Update posts/2023-12-18_admiral_1_0/admiral_1_0.qmd Co-authored-by: Edoardo Mancini <[email protected]> * chore: #96 remove duplicate post. enable dark mode * feat: #96 way back machine introduced * fix: #96 review comments * chore: #96 style and spelling * chore: #96 ignore appsilon link. spelling --------- Co-authored-by: Edoardo Mancini <[email protected]>
1 parent 97193e5 commit 3221e3a

15 files changed

+323
-62
lines changed

.lycheeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ https://pharmaverse.github.io/blog/posts/2023-06-27_hackathon_app/
88
https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f
99
https://go.appsilon.com/demo-apps
1010
https://doi.org/10.1177/17407745221123244
11+
https://appsilon.com/static/35215a117d1bc17fac2179f059c3709f/rhino_fda_pilot_r_shiny_app_e-ctd.webm

R/create_blogpost.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ c(
1515

1616
# Fill in the info, e.g.:
1717
create_post(
18-
post_name = "pharmaverse story", # needs to be character vector (length 1)
19-
post_date = "2023-08-30", # needs to be character vector (length 1)
18+
post_name = "admiral_1_0", # needs to be character vector (length 1)
19+
post_date = "2023-12-18", # needs to be character vector (length 1)
2020
description = "", # you can fill the description in later as well
21-
author = c("Nicholas Eugenio"), # one or more authors are permitted
22-
cover_image = "pharmaverse", # chose one of the above (see line 8)
23-
tags = c("community") # chose (multiple) from line 10
21+
author = c("Ben Straub"), # one or more authors are permitted
22+
cover_image = "new_features", # chose one of the above (see line 8)
23+
tags = c("admiral") # chose (multiple) from line 10
2424
)
2525

2626

_quarto.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ format:
3232
html:
3333
theme:
3434
light: [minty, ember.scss]
35+
dark: darkly
3536
#ember.scss
3637
css: styles.css
3738
# include-after-body: plausible.html

inst/WORDLIST.txt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,29 @@ traceRedir
514514
pKobZqjlXChj
515515
si
516516
vehIoJgdA
517-
youtu
517+
youtuABLFL
518+
admiraldisc
519+
admiraldiscovery
520+
advs
521+
AGEU
522+
AVALU
523+
bmi
524+
BMI
525+
BMIBL
526+
CANCTRFL
527+
changelog
528+
cheatsheet
529+
CMCAT
530+
CMSEQ
531+
codebase
532+
DTHFL
533+
ef
534+
EOSDT
535+
LSTALVDT
536+
msrc
537+
onboarding
538+
PRSEQ
539+
TRTEDT
540+
wayback
541+
ABLFL
542+
youtu

media/new_features.jpg

78.4 KB
Loading
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
---
2+
title: "admiral 1.0.0"
3+
author:
4+
- name: Ben Straub
5+
description: "1.0.0 brings a commitment to stability, new features, a few bug fixes, argument alignment and onboarding resources!"
6+
date: "2024-01-04"
7+
# please do not use any non-default categories.
8+
# You can find the default categories in the repository README.md
9+
categories: [admiral, ADaMs]
10+
# feel free to change the image
11+
image: "new_features.jpg"
12+
13+
---
14+
15+
<!--------------- typical setup ----------------->
16+
17+
```{r setup, include=FALSE}
18+
long_slug <- "2023-12-18_admiral_1_0"
19+
# renv::use(lockfile = "renv.lock")
20+
```
21+
22+
<!--------------- post begins here ----------------->
23+
24+
[`admiral 1.0.0`](https://pharmaverse.github.io/admiral/index.html) is out on [CRAN](https://cran.r-project.org/web/packages/admiral/index.html). This release brings several new features to your tool set
25+
for working with ADaMs in R. [`admiral 1.0.0`](https://pharmaverse.github.io/admiral/index.html) also brings needed stability to users who were wishing
26+
to adopt [admiral](https://pharmaverse.github.io/admiral/index.html), but were a little worried by the fast deprecation and experimentation for `pre-v1.0.0` releases.
27+
28+
This blog post will discuss our commitment to stability, walk you through the new features available, discuss some of the bug fixes, a push for common APIs across our functions, and showcase the resources available to help you on-board to [admiral](https://pharmaverse.github.io/admiral/index.html).
29+
30+
# Commitment to Stability
31+
32+
`{admiral}` was born out of a conversation between Thomas Neitmann and Michael Rimler almost three years ago. Check out this [history blog post](https://pharmaverse.github.io/blog/posts/2023-10-10_pharmaverse_story/pharmaverse_story.html) for some of additional context on its development. Over the last three years, we have worked at a furious pace to produce functions that can do almost all derivations needed for common ADaMs. However, we have noticed that some functions are very similar to others and with some minor tweaks could be made redundant in favor of other functions. This has lead to some deprecation of either whole functions or arguments as we have sought to consolidate. Unfortunately, this creates a lot of frustration for users.
33+
34+
Enter Superseded!!
35+
36+
Now with the release of `1.0.0` we are going to _supersede_ functions going forward. This is the process where when we introduce new functions to replace other functions, we will no longer fast-deprecate the replaced functions. Now we will supersede them, i.e. we will keep the function in the codebase for a long time, but recommend the use of the new function. If the function were to be removed from the codebase this will be done many years from the time it is superseded. Please note that although superseded functions are not in scope for active development, any bugs identified within them will nevertheless be fixed.
37+
38+
39+
# New Features
40+
41+
We have 3 new functions available in this release:
42+
43+
* [derive_vars_extreme_event()](https://pharmaverse.github.io/admiral/reference/derive_vars_extreme_event.html)
44+
* [derive_var_merged_ef_msrc()](https://pharmaverse.github.io/admiral/reference/derive_var_merged_ef_msrc.html)
45+
* [derive_vars_computed()](https://pharmaverse.github.io/admiral/reference/derive_vars_computed.html)
46+
47+
and a new option in [derive_var_atoxgr_dir()](https://pharmaverse.github.io/admiral/reference/derive_var_atoxgr_dir.html) and [derive_var_anrind()](https://pharmaverse.github.io/admiral/reference/derive_var_anrind.html) to handle floating point issues.
48+
49+
## `derive_vars_extreme_event()`
50+
51+
This function takes available records from user-defined events by selecting the extreme observations and appending them as a variable(s) to your dataset. [derive_vars_extreme_event()](https://pharmaverse.github.io/admiral/reference/derive_vars_extreme_event.html) works similar to [`derive_extreme_event()`](https://pharmaverse.github.io/admiral/reference/derive_extreme_event.html), but instead of adding observations the function will add variable(s).
52+
53+
Let's take a peek with a very simple example where we just use ADSL! The documentation for
54+
[derive_vars_extreme_event()](https://pharmaverse.github.io/admiral/reference/derive_vars_extreme_event.html) has a much richer example with events from other domains that is more aligned to where you would use this function.
55+
56+
Let us make some dummy `ADSL` data and load up our packages. The goal here is to add two new variables `LSTALVDT` and `DTHFL` based on a list of objects that are used to specify the following:
57+
58+
- the dataset to look at
59+
- a set of conditions
60+
- what to set the values for the new variables
61+
62+
```{r, message = FALSE, warning = FALSE}
63+
library(tibble)
64+
library(admiral)
65+
library(lubridate)
66+
67+
adsl <- tribble(
68+
~STUDYID, ~USUBJID, ~TRTEDT, ~DTHDT,
69+
"PILOT01", "01-1130", ymd("2014-08-16"), ymd("2014-09-13"),
70+
"PILOT01", "01-1133", ymd("2013-04-28"), ymd(""),
71+
"PILOT01", "01-1211", ymd("2013-01-12"), ymd(""),
72+
"PILOT01", "09-1081", ymd("2014-04-27"), ymd(""),
73+
"PILOT01", "09-1088", ymd("2014-10-09"), ymd("2014-11-01"),
74+
)
75+
```
76+
77+
78+
79+
In this example, we only use `ADSL` as the source dataset, so it is a bit contrived, but much more compact for us. Note the use of the `events` that is taking in our list of event objects and the different conditions and values we set to create our `LSTALVDT` and `DTHFL` variables.
80+
81+
```{r}
82+
derive_vars_extreme_event(
83+
adsl,
84+
by_vars = exprs(STUDYID, USUBJID),
85+
events = list(
86+
event(
87+
dataset_name = "adsl",
88+
condition = !is.na(DTHDT),
89+
set_values_to = exprs(LSTALVDT = DTHDT, DTHFL = "Y")
90+
),
91+
event(
92+
dataset_name = "adsl",
93+
condition = !is.na(TRTEDT),
94+
set_values_to = exprs(LSTALVDT = TRTEDT, DTHFL = "N")
95+
)
96+
),
97+
source_datasets = list(adsl = adsl),
98+
order = exprs(LSTALVDT),
99+
mode = "last",
100+
new_vars = exprs(LSTALVDT = LSTALVDT, DTHFL = DTHFL)
101+
)
102+
```
103+
104+
Okay! We used a very small example to showcase how to find extreme observations and
105+
appending this information as new variables to our `ADSL` dataset. Highly recommend checking
106+
out the more detailed example in the [function documentation](https://pharmaverse.github.io/admiral/reference/derive_vars_extreme_event.html) to see its true power!
107+
108+
## `derive_var_merged_ef_msrc()`
109+
110+
This function has some similarity to [derive_vars_extreme_event()](https://pharmaverse.github.io/admiral/reference/derive_vars_extreme_event.html), but now we are only looking at adding a single flag variable based on checking conditions across multiple datasets.
111+
112+
We develop some _simple_ dummy data for `ADSL`, `CM` and `PR`. Our goal is to flag patients who have `CMCAT = "ANTI-CANCER"` in the `CM` dataset or have records in the `PR` dataset. Any participants who meet these conditions will have our new variable `CANCTRFL` set as `"Y"`.
113+
114+
```{r, message = FALSE, warning = FALSE}
115+
adsl <- tribble(
116+
~USUBJID,
117+
"1",
118+
"2",
119+
"3",
120+
"4",
121+
)
122+
123+
cm <- tribble(
124+
~USUBJID, ~CMCAT, ~CMSEQ,
125+
"1", "ANTI-CANCER", 1,
126+
"1", "GENERAL", 2,
127+
"2", "GENERAL", 1,
128+
"3", "ANTI-CANCER", 1
129+
)
130+
131+
pr <- tribble(
132+
~USUBJID, ~PRSEQ,
133+
"2", 1,
134+
"3", 1
135+
)
136+
```
137+
138+
139+
Now we have the argument `flag_events` that takes a list of objects where we define the conditions and datasets to check in.
140+
141+
```{r}
142+
derive_var_merged_ef_msrc(
143+
adsl,
144+
flag_events = list(
145+
flag_event(
146+
dataset_name = "cm",
147+
condition = CMCAT == "ANTI-CANCER"
148+
),
149+
flag_event(
150+
dataset_name = "pr"
151+
)
152+
),
153+
source_datasets = list(cm = cm, pr = pr),
154+
by_vars = exprs(USUBJID),
155+
new_var = CANCTRFL
156+
)
157+
```
158+
159+
Let's go! We searched over multiple datasets, `CM` and `PR`, with multiple conditions and appended a new variable `CANCTRFL` to `ADSL` setting to `"Y"` if those conditions were met.
160+
161+
## `derive_vars_computed()`
162+
163+
This function is very similar to [derive_param_computed()](https://pharmaverse.github.io/admiral/reference/derive_param_computed.html), but instead of adding observations we are going to add variable(s). Very handy when wanting to add some additional variables to `ADSL`, e.g. baseline variables.
164+
165+
Let's make some dummy data for an `ADSL` and `ADVS`. Our goal is to derive a `BMIBL` variable pulled from `ADVS` and append to `ADSL`.
166+
167+
```{r}
168+
adsl <- tribble(
169+
~STUDYID, ~USUBJID, ~AGE, ~AGEU,
170+
"PILOT01", "01-1302", 61, "YEARS",
171+
"PILOT01", "17-1344", 64, "YEARS"
172+
)
173+
174+
advs <- tribble(
175+
~STUDYID, ~USUBJID, ~PARAMCD, ~PARAM, ~VISIT, ~AVAL, ~AVALU, ~ABLFL,
176+
"PILOT01", "01-1302", "HEIGHT", "Height (cm)", "SCREENING", 177.8, "cm", "Y",
177+
"PILOT01", "01-1302", "WEIGHT", "Weight (kg)", "SCREENING", 81.19, "kg", "N",
178+
"PILOT01", "01-1302", "WEIGHT", "Weight (kg)", "BASELINE", 82.1, "kg", "Y",
179+
"PILOT01", "01-1302", "WEIGHT", "Weight (kg)", "WEEK 2", 81.19, "kg", "N",
180+
"PILOT01", "01-1302", "WEIGHT", "Weight (kg)", "WEEK 4", 82.56, "kg", "N",
181+
"PILOT01", "01-1302", "WEIGHT", "Weight (kg)", "WEEK 6", 80.74, "kg", "N",
182+
"PILOT01", "17-1344", "HEIGHT", "Height (cm)", "SCREENING", 163.5, "cm", "Y",
183+
"PILOT01", "17-1344", "WEIGHT", "Weight (kg)", "SCREENING", 58.06, "kg", "N",
184+
"PILOT01", "17-1344", "WEIGHT", "Weight (kg)", "BASELINE", 58.06, "kg", "Y",
185+
"PILOT01", "17-1344", "WEIGHT", "Weight (kg)", "WEEK 2", 58.97, "kg", "N",
186+
"PILOT01", "17-1344", "WEIGHT", "Weight (kg)", "WEEK 4", 57.97, "kg", "N",
187+
"PILOT01", "17-1344", "WEIGHT", "Weight (kg)", "WEEK 6", 58.97, "kg", "N"
188+
)
189+
```
190+
191+
Take a look at how we use `new_vars` and `filter_add`. We use a function inside of `new_vars` to help us calculate the `BMI` while using the `filter_add` argument to only look at baseline records for the calculation.
192+
193+
```{r}
194+
derive_vars_computed(
195+
dataset = adsl,
196+
dataset_add = advs,
197+
by_vars = exprs(STUDYID, USUBJID),
198+
parameters = c("WEIGHT"),
199+
constant_by_vars = exprs(STUDYID, USUBJID),
200+
constant_parameters = c("HEIGHT"),
201+
new_vars = exprs(BMIBL = compute_bmi(height = AVAL.HEIGHT, weight = AVAL.WEIGHT)),
202+
filter_add = ABLFL == "Y"
203+
)
204+
```
205+
206+
Alright! Simple enough. We just took records from `ADVS`to help us calculate the `BMI` at baseline using this function and appended our new variable to `ADSL`.
207+
208+
# Argument Alignment and Bug Fixes
209+
210+
## Argument Alignment
211+
212+
A huge push was made for `1.0.0` to help align our arguments across all of `{admiral}` functions. What does this mean? We identified arguments in functions where the argument did the same things but was slightly named differently. For `1.0.0`, we really want users to have a solid API for `{admiral}` functions.
213+
214+
Let's take a peak at the function [`consolidate_metadata()`](https://pharmaverse.github.io/admiral/reference/consolidate_metadata.html) to even better understand our goal here.
215+
216+
```
217+
consolidate_metadata(
218+
datasets,
219+
key_vars,
220+
source_var = SOURCE,
221+
check_vars = "warning",
222+
check_keys,
223+
check_type = "error"
224+
)
225+
```
226+
227+
In previous versions of `{admiral}` the `consolidate_metadata()` function had the argument `check_keys`, which helps to check uniqueness. Other functions had a similar argument, but were called `check_unique`. Therefore, to better align our common API for `{admiral}` functions we decided to rename the `check_keys` argument to `check_unique`. You can follow the discussion around this renaming effort in this [GitHub Issue](https://github.com/pharmaverse/admiral/issues/2184).
228+
229+
```{r, fig.align = 'center', echo=FALSE}
230+
knitr::include_graphics("check.png")
231+
```
232+
233+
234+
The argument has a deprecated tag in the function documentation and will issue a warning to users. There was quite a bit of renaming of arguments for `1.0.0` so there are quite a few of these tags in our documentation. In subsequent releases, these arguments will be removed. Please see the [changelog](https://pharmaverse.github.io/admiral/news/index.html#admiral-100) if you would like to explore other functions that had arguments renamed. The issues are linked to each rename so you can follow along with the discussions!
235+
236+
## Bug Fixes
237+
238+
We love fixing bugs and take them incredibly seriously - especially when identified by members from the community.
239+
240+
If you find a pesky bug, please fill out a [Bug Report](https://github.com/pharmaverse/admiral/issues/new/choose) on our Issues Tab.
241+
242+
Each bug fixed by our development team is documented in our [changelog](https://pharmaverse.github.io/admiral/news/index.html#updates-of-existing-functions-1-0-0) with the Issue linked.
243+
244+
```{r, fig.align = 'center', echo=FALSE}
245+
knitr::include_graphics("issue_tag.png")
246+
```
247+
248+
249+
For example, if you click through the issue for [`derive_extreme_event()`](https://github.com/pharmaverse/admiral/issues/2291) that identified a problem where the `condition` was ignored if the `mode` argument was used, you can see the Bug Report along with a reproducible example. You can also see the Pull Request for the exact code changes that are addressing this bug linked in the Issue! Way cool!
250+
251+
252+
# New On-boarding Resources
253+
254+
`{admiral}` has a lot of functions for working with ADaMs. This can be overwhelming for new users and we really sympathize. To help new users onboarding to `{admiral}` we have developed the following resources:
255+
256+
## [admiraldiscovery](https://pharmaverse.github.io/admiraldiscovery/index.html)
257+
258+
This is a dedicated website that lists out in a tabular format standard ADaM datasets and their common variables with corresponding `{admiral}` functions that could be used to create the variables. Very handy when you just want to get some starter code on deriving `EOSDT` or `TRTSDT`!
259+
260+
261+
```{r, fig.align = 'center', echo=FALSE}
262+
knitr::include_graphics("admiraldisc.png")
263+
```
264+
265+
266+
## [admiral Cheat Sheet](https://github.com/pharmaverse/admiral/blob/main/inst/cheatsheet/admiral_cheatsheet.pdf)
267+
268+
Inspired by other R package cheat sheets! We try and surface commonly needed functions for doing ADaM derivations with simple tables to show how the data is transforming.
269+
270+
```{r, fig.align = 'center', echo=FALSE}
271+
knitr::include_graphics("cheatsheet.png")
272+
```
273+
274+
## Way Back Machine
275+
276+
Studies can last a long time. Adopting R as your primary analysis language for your study can introduce certain risks around package dependencies. Fixing those dependencies to certain package versions can help mitigate those risks. Unfortunately, as package websites are updated those helpful documents, examples and vignettes can be lost as the version changes. Do not lose heart `{admiral}` users. If you decided to fix to a certain version of `{admiral}`, we have you covered with our __Way Back Machine__ that allows you to change the website documentation back to the version you are using.
277+
278+
```{r, fig.align = 'center', echo=FALSE}
279+
knitr::include_graphics("wayback.png")
280+
```
281+
282+
<!--------------- appendices go here ----------------->
283+
284+
```{r, echo=FALSE}
285+
source("appendix.R")
286+
insert_appendix(
287+
repo_spec = "pharmaverse/blog",
288+
name = long_slug
289+
)
290+
```
60.6 KB
Loading
549 KB
Loading
41.8 KB
Loading
21.4 KB
Loading
347 KB
Loading
51.6 KB
Loading

0 commit comments

Comments
 (0)