Repository: pharmaverse/admiral
Pull request #2736: Closes #2735 derive extreme event examples
Author: login: manciniedoardo
Created: 2025-05-19T15:56:09Z | Merged: 2025-05-23T10:53:41Z

Thank you for your Pull Request! We have developed this task checklist from the [Development Process Guide](https://pharmaverse.github.io/admiral/CONTRIBUTING.html#detailed-development-process) to help with the final steps of the process. Completing the below tasks helps to ensure our reviewers can maximize their time on your code as well as making sure the admiral codebase remains robust and consistent.   

Please check off each taskbox as an acknowledgment that you completed the task or check off that it is not relevant to your Pull Request. This checklist is part of the Github Action workflows and the Pull Request will not be merged into the `main` branch until you have checked off each task.

- [x] Place Closes #<insert_issue_number> into the beginning of your Pull Request Title (Use Edit button in top-right if you need to update)
- [x] Code is formatted according to the [tidyverse style guide](https://style.tidyverse.org/). Run `styler::style_file()` to style R and Rmd files
- [x] Updated relevant unit tests or have written new unit tests, which should consider realistic data scenarios and edge cases, e.g. empty datasets, errors, boundary cases etc. - See [Unit Test Guide](https://pharmaverse.github.io/admiraldev/articles/unit_test_guidance.html#tests-should-be-robust-to-cover-realistic-data-scenarios)
- [x] If you removed/replaced any function and/or function parameters, did you fully follow the [deprecation guidance](https://pharmaverse.github.io/admiraldev/articles/programming_strategy.html#deprecation)?
- [x] Review the [Cheat Sheet](https://github.com/pharmaverse/admiral/blob/main/inst/cheatsheet/admiral_cheatsheet.pdf). Make any required updates to it by editing the file `inst/cheatsheet/admiral_cheatsheet.pptx` and re-upload a PDF and a PNG version of it to the same folder. (The PNG version can be created by taking a screenshot of the PDF version.)
- [x] Update to all relevant roxygen headers and examples, including keywords and families. Refer to the [categorization of functions](https://pharmaverse.github.io/admiraldev/articles/programming_strategy.html#categorization-of-functions) to tag appropriate keyword/family.
- [x] Run `devtools::document()` so all `.Rd` files in the `man` folder and the `NAMESPACE` file in the project root are updated appropriately
- [x] Address any updates needed for vignettes and/or templates
- [x] Update `NEWS.md` under the header `# admiral (development version)` if the changes pertain to a user-facing function (i.e. it has an `@export` tag) or documentation aimed at users (rather than developers). A Developer Notes section is available in `NEWS.md` for tracking developer-facing issues.  
- [x] Build admiral site `pkgdown::build_site()` and check that all affected examples are displayed correctly and that all new functions occur on the "[Reference](https://pharmaverse.github.io/admiral/reference/index.html)" page. 
- [x] Address or fix all lintr warnings and errors - `lintr::lint_package()`
- [x] Run `R CMD check` locally and address all errors and warnings - `devtools::check()`
- [x] Link the issue in the Development Section on the right hand side.
- [x] Address all merge conflicts and resolve appropriately
- [x] Pat yourself on the back for a job well done! Much love to your accomplishment!


Linked issue #2735: Examples enhancement: `derive_extreme_event()`
### Please select a category the issue is focused on?

Function Documentation

### Let us know where something needs a refresh or put your idea here!

Enhancement of roxygen documentation for `derive_extreme_event()` as per #2700

Diff:
diff --git a/NEWS.md b/NEWS.md
index 7b13c3168d..4819e1b560 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -58,6 +58,7 @@ records. (#2683)
     - `derive_extreme_records()` (#2585)
     - `derive_param_tte()` (#2704)
     - `derive_summary_records()` (#2707)
+    - `derive_extreme_event()` (#2735)
     - `derive_vars_joined()` (#2727)
     - `derive_vars_merged()` (#2727)
 
diff --git a/R/derive_extreme_event.R b/R/derive_extreme_event.R
index 3bdb504bb4..1f98fb3ec7 100644
--- a/R/derive_extreme_event.R
+++ b/R/derive_extreme_event.R
@@ -18,6 +18,8 @@
 #'   For `event_joined()` events the observations are selected by calling
 #'   `filter_joined()`. The `condition` field is passed to the `filter_join` argument.
 #'
+#' @permitted [event]
+#'
 #' @param tmp_event_nr_var Temporary event number variable
 #'
 #'   The specified variable is added to all source datasets and is set to the
@@ -28,6 +30,8 @@
 #'
 #'   The variable is not included in the output dataset.
 #'
+#' @permitted [var]
+#'
 #' @param order Sort order
 #'
 #'   If a particular event from `events` has more than one observation, within
@@ -35,8 +39,7 @@
 #'
 #'   `r roxygen_order_na_handling()`
 #'
-#' @permitted list of expressions created by `exprs()`, e.g.,
-#'   `exprs(ADT, desc(AVAL))`
+#' @permitted [var_list]
 #'
 #' @param mode Selection mode (first or last)
 #'
@@ -44,13 +47,35 @@
 #'   `"first"`/`"last"` is used to select the first/last record of this type of
 #'   event sorting by `order`.
 #'
-#' @permitted `"first"`, `"last"`
+#' @permitted [mode]
 #'
 #' @param source_datasets Source datasets
 #'
 #'   A named list of datasets is expected. The `dataset_name` field of `event()`
 #'   and `event_joined()` refers to the dataset provided in the list.
 #'
+#' @permitted [dataset_list]
+#'
+#' @param set_values_to Variables to be set
+#'
+#'   The specified variables are set to the specified values for the new
+#'   observations.
+#'
+#'   Set a list of variables to some specified value for the new records
+#'   + LHS refer to a variable.
+#'   + RHS refers to the values to set to the variable. This can be a string, a
+#'   symbol, a numeric value, an expression or NA.
+#'
+#'   For example:
+#'   ```
+#'     set_values_to = exprs(
+#'       PARAMCD = "WOBS",
+#'       PARAM = "Worst Observations"
+#'     )
+#'   ```
+#'
+#' @permitted [expr_list_formula]
+#'
 #' @param keep_source_vars Variables to keep from the source dataset
 #'
 #'  For each event the specified variables are kept from the selected
@@ -59,9 +84,7 @@
 #'  the event will take precedence over the value of the `keep_source_vars`
 #'  argument.
 #'
-#' @permitted A list of expressions where each element is
-#'   a symbol or a tidyselect expression, e.g., `exprs(VISIT, VISITNUM,
-#'   starts_with("RS"))`.
+#' @permitted [var_list]
 #'
 #' @inheritParams filter_extreme
 #' @inheritParams derive_summary_records
@@ -106,44 +129,151 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(STUDYID, USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created by the following process:
+#'   \enumerate{
+#'     \item the selected record is copied,
+#'     \item the variables specified in the event's `set_values_to` (here,
+#'     `AVAL` and `AVALC`) are created/updated,
+#'     \item the variables specified in `keep_source_vars` (here, `ADY` does due
+#'     to the use of the tidyselect expression `everything()`) (plus `by_vars`
+#'     and the variables from `set_values_to`) are kept,
+#'     \item the variables specified in the global `set_values_to` (here,
+#'     `PARAM` and `PARAMCD`) are created/updated.
+#'   }
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(AVALC = "No sleeping problems", AVAL = 3)
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Events based on comparison across records (`event_joined()`)
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "Y",    4
+#' ) %>%
+#' mutate(STUDYID = "AB42")
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(STUDYID, USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
@@ -156,37 +286,62 @@
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `Y`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `"Y"`, it's enough to specify the `condition`,
+#'    because we inherit `order` and `mode` from the main
+#'    `derive_extreme_event()` call here which will automatically
+#'    select the first occurrence by `AVISITN`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL` are all `"N"` by additionally
+#'    specifying `mode = "last"` within the `event()`.
+#'  - Note now the usage of `keep_source_vars = exprs(AVISITN)`
+#'    rather than `everything()` as in the previous example. This
+#'    is done to ensure `CRIT1` and `CRIT1FL` are not populated for
+#'    the new records.
+#'
+#' @code
 #' adhy <- tribble(
-#'   ~USUBJID, ~AVISITN, ~CRIT1FL,
-#'   "1",             1, "Y",
-#'   "1",             2, "Y",
-#'   "2",             1, "Y",
-#'   "2",             2, NA_character_,
-#'   "2",             3, "Y",
-#'   "2",             4, NA_character_
+#'   ~USUBJID, ~AVISITN,              ~CRIT1, ~CRIT1FL,
+#'   "1",             1, "ALT > 2 times ULN", "N",
+#'   "1",             2, "ALT > 2 times ULN", "N",
+#'   "2",             1, "ALT > 2 times ULN", "N",
+#'   "2",             2, "ALT > 2 times ULN", "Y",
+#'   "2",             3, "ALT > 2 times ULN", "N",
+#'   "2",             4, "ALT > 2 times ULN", "Y"
 #' ) %>%
 #'   mutate(
-#'     PARAMCD = "ALKPH",
-#'     PARAM = "Alkaline Phosphatase (U/L)"
+#'     PARAMCD = "ALT",
+#'     PARAM = "ALT (U/L)",
+#'     STUDYID = "AB42"
 #'   )
 #'
 #' derive_extreme_event(
 #'   adhy,
-#'   by_vars = exprs(USUBJID),
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
-#'       condition = is.na(CRIT1FL),
-#'       set_values_to = exprs(AVALC = "N")
+#'       condition = CRIT1FL == "Y",
+#'       set_values_to = exprs(AVALC = "Y")
 #'     ),
 #'     event(
-#'       condition = CRIT1FL == "Y",
+#'       condition = CRIT1FL == "N",
 #'       mode = "last",
-#'       set_values_to = exprs(AVALC = "Y")
+#'       set_values_to = exprs(AVALC = "N")
 #'     )
 #'   ),
 #'   tmp_event_nr_var = event_nr,
@@ -194,14 +349,24 @@
 #'   mode = "first",
 #'   keep_source_vars = exprs(AVISITN),
 #'   set_values_to = exprs(
-#'     PARAMCD = "ALK2",
-#'     PARAM = "ALKPH <= 2 times ULN"
+#'     PARAMCD = "ALT2",
+#'     PARAM = "ALT > 2 times ULN"
 #'   )
-#' )
+#' ) %>%
+#'   select(-STUDYID)
+#'
+#' @caption A more complex example: Confirmed Best Overall Response
+#' (`first/last_cond_upper`, `join_type`, `source_datasets`)
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   `ADRS` dataset, as is common in many oncology trials. This example
+#'   builds on all the previous ones and thus assumes a baseline level
+#'   of confidence with `derive_extreme_event()`.
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#'   The following `ADSL` and `ADRS` datasets will be used
+#'   throughout:
+#'
+#' @code
 #' adsl <- tribble(
 #'   ~USUBJID, ~TRTSDTC,
 #'   "1",      "2020-01-01",
@@ -213,7 +378,10 @@
 #'   "7",      "2020-02-02",
 #'   "8",      "2020-02-01"
 #' ) %>%
-#'   mutate(TRTSDT = ymd(TRTSDTC))
+#' mutate(
+#'   TRTSDT = ymd(TRTSDTC),
+#'   STUDYID = "AB42"
+#' )
 #'
 #' adrs <- tribble(
 #'   ~USUBJID, ~ADTC,        ~AVALC,
@@ -243,18 +411,63 @@
 #' ) %>%
 #'   mutate(
 #'     ADT = ymd(ADTC),
+#'     STUDYID = "AB42",
 #'     PARAMCD = "OVR",
 #'     PARAM = "Overall Response by Investigator"
 #'   ) %>%
 #'   derive_vars_merged(
 #'     dataset_add = adsl,
-#'     by_vars = exprs(USUBJID),
+#'     by_vars = exprs(STUDYID, USUBJID),
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original `ADRS`
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`), we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`.
+#'
+#'     Note that the selection of `join_type = "after"` is critical here, due to the
+#'     fact that the restriction implied by `join_type` is applied before the one
+#'     implied by `first_cond_upper`. Picking the first subject (who was correctly
+#'     identified as a confirmed responder) as an example, selecting
+#'     `join_type = "all"` instead of `"after"` would mean the first `"PR"` record
+#'     from `"2020-01-01"` would also be considered when evaluating the
+#'     `all(AVALC.join %in% c("CR", "NE"))` portion of `condition`. In turn, the
+#'     condition would not be satisfied anymore, and in this case, following the
+#'     later event logic shows the subject would be considered a partial responder
+#'     instead.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory `"PR"` or `"CR"` 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    `"PR"`s.
+#'
+#'  - The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+#'    events are simpler and just require `event()` calls.
+#'
+#'  - Finally, we use a catch-all `event()` with `condition = TRUE` and
+#'    `dataset_name = "adsl"` to identify those subjects who do not appear in `ADRS`
+#'    and list their CBOR as `"MISSING"`. Note here the fact that `dataset_name` is
+#'    set to `"adsl"`, which is a new source dataset. As such it's important in the
+#'    main `derive_extreme_event()` call to list `adsl` as another source dataset
+#'    with `source_datasets = list(adsl = adsl)`.
+#'
+#' @code
 #' derive_extreme_event(
 #'   adrs,
-#'   by_vars = exprs(USUBJID),
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, ADT),
 #'   mode = "first",
@@ -267,14 +480,11 @@
 #'       ),
 #'       join_vars = exprs(AVALC, ADT),
 #'       join_type = "after",
-#'       first_cond_upper = AVALC.join == "CR" &
-#'         ADT.join >= ADT + 28,
+#'       first_cond_upper = AVALC.join == "CR" & ADT.join >= ADT + 28,
 #'       condition = AVALC == "CR" &
 #'         all(AVALC.join %in% c("CR", "NE")) &
 #'         count_vals(var = AVALC.join, val = "NE") <= 1,
-#'       set_values_to = exprs(
-#'         AVALC = "CR"
-#'       )
+#'       set_values_to = exprs(AVALC = "CR")
 #'     ),
 #'     event_joined(
 #'       description = paste(
@@ -283,14 +493,11 @@
 #'       ),
 #'       join_vars = exprs(AVALC, ADT),
 #'       join_type = "after",
-#'       first_cond_upper = AVALC.join %in% c("CR", "PR") &
-#'         ADT.join >= ADT + 28,
+#'       first_cond_upper = AVALC.join %in% c("CR", "PR") & ADT.join >= ADT + 28,
 #'       condition = AVALC == "PR" &
 #'         all(AVALC.join %in% c("CR", "PR", "NE")) &
 #'         count_vals(var = AVALC.join, val = "NE") <= 1,
-#'       set_values_to = exprs(
-#'         AVALC = "PR"
-#'       )
+#'       set_values_to = exprs(AVALC = "PR")
 #'     ),
 #'     event(
 #'       description = paste(
@@ -298,29 +505,21 @@
 #'         "after treatment start"
 #'       ),
 #'       condition = AVALC %in% c("CR", "PR", "SD") & ADT >= TRTSDT + 28,
-#'       set_values_to = exprs(
-#'         AVALC = "SD"
-#'       )
+#'       set_values_to = exprs(AVALC = "SD")
 #'     ),
 #'     event(
 #'       condition = AVALC == "PD",
-#'       set_values_to = exprs(
-#'         AVALC = "PD"
-#'       )
+#'       set_values_to = exprs(AVALC = "PD")
 #'     ),
 #'     event(
 #'       condition = AVALC %in% c("CR", "PR", "SD", "NE"),
-#'       set_values_to = exprs(
-#'         AVALC = "NE"
-#'       )
+#'       set_values_to = exprs(AVALC = "NE")
 #'     ),
 #'     event(
-#'       description = "set response to MISSING for patients without records in ADRS",
+#'       description = "Set response to MISSING for patients without records in ADRS",
 #'       dataset_name = "adsl",
 #'       condition = TRUE,
-#'       set_values_to = exprs(
-#'         AVALC = "MISSING"
-#'       ),
+#'       set_values_to = exprs(AVALC = "MISSING"),
 #'       keep_source_vars = exprs(TRTSDT)
 #'     )
 #'   ),
@@ -329,8 +528,12 @@
 #'     PARAM = "Best Confirmed Overall Response by Investigator"
 #'   )
 #' ) %>%
-#'   filter(PARAMCD == "CBOR")
+#'   filter(PARAMCD == "CBOR") %>%
+#'   select(-STUDYID, -ADTC)
 #'
+#' @caption Further examples
+#' @info Equivalent examples for using the`check_type` argument can be found in
+#'   `derive_extreme_records()`.
 derive_extreme_event <- function(dataset = NULL,
                                  by_vars,
                                  events,
diff --git a/R/derive_summary_records.R b/R/derive_summary_records.R
index 7b6611ee34..9c48d46435 100644
--- a/R/derive_summary_records.R
+++ b/R/derive_summary_records.R
@@ -24,12 +24,16 @@
 #'   Observations from the specified dataset are going to be used to calculate and added
 #'   as new records to the input dataset (`dataset`).
 #'
+#' @permitted [dataset]
+#'
 #' @param dataset_ref Reference dataset
 #'
 #'   The variables specified for `by_vars` are expected. For each
 #'   observation of the specified dataset a new observation is added to the
 #'   input dataset.
 #'
+#' @permitted [dataset]
+#'
 #' @param by_vars Grouping variables
 #'
 #'   Variables to consider for generation of groupwise summary
@@ -38,6 +42,8 @@
 #'
 #'   `r roxygen_param_by_vars()`
 #'
+#' @permitted [var_list]
+#'
 #' @param filter_add Filter condition as logical expression to apply during
 #'   summary calculation. By default, filtering expressions are computed within
 #'   `by_vars` as this will help when an aggregating, lagging, or ranking
@@ -50,6 +56,8 @@
 #'   + `filter_add = (dplyr::n() > 2)` will filter n count of `by_vars` greater
 #'   than 2.
 #'
+#' @permitted [condition]
+#'
 #' @param set_values_to Variables to be set
 #'
 #'   The specified variables are set to the specified values for the new
@@ -69,14 +77,15 @@
 #'     )
 #'   ```
 #'
+#' @permitted [expr_list_summary]
+#'
 #' @param missing_values Values for missing summary values
 #'
 #'   For observations of the reference dataset (`dataset_ref`) which do not have a
 #'   complete mapping defined by the summarization defined in `set_values_to`.  Only variables
 #'   specified for `set_values_to` can be specified for `missing_values`.
 #'
-#' @permitted named list of expressions, e.g.,
-#'   `exprs(AVAL = -9999)`
+#' @permitted [expr_list_summary]
 #'
 #' @return A data frame with derived records appended to original dataset.
 #'
diff --git a/R/filter_extreme.R b/R/filter_extreme.R
index 0d22ff31b7..7c53a6e9ec 100644
--- a/R/filter_extreme.R
+++ b/R/filter_extreme.R
@@ -4,16 +4,19 @@
 #'
 #' @param dataset `r roxygen_param_dataset(expected_vars = c("by_vars", "order"))`
 #'
+#' @permitted [dataset]
+#'
 #' @param by_vars Grouping variables
 #'
 #'   `r roxygen_param_by_vars()`
 #'
+#' @permitted [var_list]
+#'
 #' @param order Sort order
 #'
 #'   Within each by group the observations are ordered by the specified order.
 #'
-#' @permitted list of expressions created by `exprs()`, e.g.,
-#'   `exprs(ADT, desc(AVAL))`
+#' @permitted [var_list]
 #'
 #' @param mode Selection mode (first or last)
 #'
diff --git a/inst/WORDLIST b/inst/WORDLIST
index a3f3383ce8..172c28163b 100644
--- a/inst/WORDLIST
+++ b/inst/WORDLIST
@@ -9,6 +9,7 @@ ADNCA
 ADPC
 ADPP
 ADPPK
+ADRS
 ADSL
 ADVS
 ADaM
@@ -47,6 +48,7 @@ Basetype
 Bazett
 Bazett's
 Biologics
+CBOR
 CDISC
 CKD
 CMD
@@ -329,6 +331,7 @@ recoded
 renv
 repo
 reproducibility
+responder
 responders
 rlang
 roche
diff --git a/man/derive_extreme_event.Rd b/man/derive_extreme_event.Rd
index 52338d4745..baec459322 100644
--- a/man/derive_extreme_event.Rd
+++ b/man/derive_extreme_event.Rd
@@ -23,12 +23,14 @@ derive_extreme_event(
 The variables specified by the \code{by_vars} and \code{order} arguments are expected to be in the dataset.
 
 \describe{
+\item{Permitted values}{a dataset, i.e., a \code{data.frame} or tibble}
 \item{Default value}{none}
 }}
 
 \item{by_vars}{Grouping variables
 
 \describe{
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -44,6 +46,7 @@ For \code{event_joined()} events the observations are selected by calling
 \code{filter_joined()}. The \code{condition} field is passed to the \code{filter_join} argument.
 
 \describe{
+\item{Permitted values}{an \code{event()} or \code{event_joined()} object}
 \item{Default value}{none}
 }}
 
@@ -58,6 +61,7 @@ records from more than one event are selected.
 The variable is not included in the output dataset.
 
 \describe{
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -69,8 +73,7 @@ the event and by group, the records are ordered by the specified order.
 For handling of \code{NA}s in sorting variables see \href{../articles/generic.html#sort_order}{Sort Order}.
 
 \describe{
-\item{Permitted values}{list of expressions created by \code{exprs()}, e.g.,
-\code{exprs(ADT, desc(AVAL))}}
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{none}
 }}
 
@@ -91,6 +94,7 @@ A named list of datasets is expected. The \code{dataset_name} field of \code{eve
 and \code{event_joined()} refers to the dataset provided in the list.
 
 \describe{
+\item{Permitted values}{named list of datasets, e.g., \code{list(adsl = adsl, ae = ae)}}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -114,20 +118,20 @@ Set a list of variables to some specified value for the new records
 \itemize{
 \item LHS refer to a variable.
 \item RHS refers to the values to set to the variable. This can be a string, a
-symbol, a numeric value, an expression or NA. If summary functions are
-used, the values are summarized by the variables specified for \code{by_vars}.
+symbol, a numeric value, an expression or NA.
 }
 
 For example:
 
 \if{html}{\out{<div class="sourceCode">}}\preformatted{  set_values_to = exprs(
-    AVAL = sum(AVAL),
-    DTYPE = "AVERAGE",
+    PARAMCD = "WOBS",
+    PARAM = "Worst Observations"
   )
 }\if{html}{\out{</div>}}
 
 \describe{
-\item{Default value}{none}
+\item{Permitted values}{list of named expressions created by a formula using \code{exprs()}, e.g., \code{exprs(AVALC = VSSTRESC, AVAL = yn_to_numeric(AVALC))}}
+\item{Default value}{\code{NULL}}
 }}
 
 \item{keep_source_vars}{Variables to keep from the source dataset
@@ -139,8 +143,7 @@ the event will take precedence over the value of the \code{keep_source_vars}
 argument.
 
 \describe{
-\item{Permitted values}{A list of expressions where each element is
-a symbol or a tidyselect expression, e.g., \code{exprs(VISIT, VISITNUM, starts_with("RS"))}.}
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{\code{exprs(everything())}}
 }}
 }
@@ -191,44 +194,186 @@ than the input datasets. If this causes memory issues, please try setting
 the admiral option \code{save_memory} to \code{TRUE} (see \code{set_admiral_options()}).
 This reduces the memory consumption but increases the run-time.
 }
-\examples{
-library(tibble)
-library(dplyr)
-library(lubridate)
-
-adqs <- tribble(
-  ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-  "1",      "NO SLEEP",     "N",              1,
-  "1",      "WAKE UP",      "N",              2,
-  "1",      "FALL ASLEEP",  "N",              3,
-  "2",      "NO SLEEP",     "N",              1,
-  "2",      "WAKE UP",      "Y",              2,
-  "2",      "WAKE UP",      "Y",              3,
-  "2",      "FALL ASLEEP",  "N",              4,
-  "3",      "NO SLEEP",     NA_character_,    1
-)
+\seealso{
+\code{\link[=event]{event()}}, \code{\link[=event_joined]{event_joined()}}, \code{\link[=derive_vars_extreme_event]{derive_vars_extreme_event()}}
+
+BDS-Findings Functions for adding Parameters/Records: 
+\code{\link{default_qtc_paramcd}()},
+\code{\link{derive_expected_records}()},
+\code{\link{derive_extreme_records}()},
+\code{\link{derive_locf_records}()},
+\code{\link{derive_param_bmi}()},
+\code{\link{derive_param_bsa}()},
+\code{\link{derive_param_computed}()},
+\code{\link{derive_param_doseint}()},
+\code{\link{derive_param_exist_flag}()},
+\code{\link{derive_param_exposure}()},
+\code{\link{derive_param_framingham}()},
+\code{\link{derive_param_map}()},
+\code{\link{derive_param_qtc}()},
+\code{\link{derive_param_rr}()},
+\code{\link{derive_param_wbc_abs}()},
+\code{\link{derive_summary_records}()}
+}
+\concept{der_prm_bds_findings}
+\keyword{der_prm_bds_findings}
+\section{Examples}{
+\subsection{Add a new record for the worst observation using \code{event()} objects}{
+
+For each subject, the observation containing the worst sleeping problem
+(if any exist) should be identified and added as a new record, retaining
+all variables from the original observation. If multiple occurrences of the
+worst sleeping problem occur, or no sleeping problems, then take the
+observation occurring at the latest day.
+\itemize{
+\item The groups for which new records are added are specified by the \code{by_vars}
+argument. Here for each \emph{subject} a record should be added. Thus
+\code{by_vars = exprs(STUDYID, USUBJID)} is specified.
+\item The sets of possible sleeping problems are passed through the \code{events}
+argument as \code{event()} objects. Each event contains a \code{condition} which
+may or may not be satisfied by each record (or possibly a group of
+records) within the input dataset \code{dataset}. Summary functions such as
+\code{any()} and \code{all()} are often handy to use within conditions, as is done
+here for the third event, which checks that the subject had no sleeping
+issues. The final event uses a catch-all \code{condition = TRUE} to ensure all
+subjects have a new record derived. Note that in this example, as no
+condition involves analysis of \strong{cross-comparison values of within  records},
+it is sufficient to use \code{event()} objects rather than \code{event_joined()} -
+see the next example for a more complex condition.
+\item If any subject has one or more records satisfying the conditions from
+events, we can select just one record using the \code{order} argument. In this
+example, the first argument passed to \code{order} is \code{event_nr}, which is a
+temporary variable created through the \code{tmp_event_nr_var} argument, which
+numbers the events consecutively. Since \code{mode = "first"}, we only consider
+the first event for which a condition is satisfied. Within that event, we
+consider only the observation with the latest day, because the second
+argument for the order is \code{desc(ADY)}.
+\item Once a record is identified as satisfying an event's condition, a new
+observation is created by the following process:
+\enumerate{
+\item the selected record is copied,
+\item the variables specified in the event's \code{set_values_to} (here,
+\code{AVAL} and \code{AVALC}) are created/updated,
+\item the variables specified in \code{keep_source_vars} (here, \code{ADY} does due
+to the use of the tidyselect expression \code{everything()}) (plus \code{by_vars}
+and the variables from \code{set_values_to}) are kept,
+\item the variables specified in the global \code{set_values_to} (here,
+\code{PARAM} and \code{PARAMCD}) are created/updated.
+}
+}
+
+\if{html}{\out{<div class="sourceCode r">}}\preformatted{library(tibble, warn.conflicts = FALSE)
+library(dplyr, warn.conflicts = FALSE)
+library(lubridate, warn.conflicts = FALSE)
+
+adqs1 <- tribble(
+  ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+  "1",      "NO SLEEP",       "N",              1,
+  "1",      "WAKE UP 3X",     "N",              2,
+  "2",      "NO SLEEP",       "N",              1,
+  "2",      "WAKE UP 3X",     "Y",              2,
+  "2",      "WAKE UP 3X",     "Y",              3,
+  "3",      "NO SLEEP",       NA_character_,    1
+) \%>\%
+mutate(STUDYID = "AB42")
 
-# Add a new record for each USUBJID storing the the worst sleeping problem.
 derive_extreme_event(
-  adqs,
-  by_vars = exprs(USUBJID),
+  adqs1,
+  by_vars = exprs(STUDYID, USUBJID),
   events = list(
     event(
       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
     ),
     event(
-      condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-      set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+      condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+      set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+    ),
+    event(
+      condition = all(AVALC == "N"),
+      set_values_to = exprs(AVALC = "No sleeping problems", AVAL = 3)
+    ),
+    event(
+      condition = TRUE,
+      set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+    )
+  ),
+  tmp_event_nr_var = event_nr,
+  order = exprs(event_nr, desc(ADY)),
+  mode = "first",
+  set_values_to = exprs(
+    PARAMCD = "WSP",
+    PARAM = "Worst Sleeping Problem"
+  ),
+  keep_source_vars = exprs(everything())
+) \%>\%
+select(-STUDYID)
+#> # A tibble: 9 × 6
+#>   USUBJID PARAMCD    AVALC                   ADY  AVAL PARAM                 
+#>   <chr>   <chr>      <chr>                 <dbl> <dbl> <chr>                 
+#> 1 1       NO SLEEP   N                         1    NA <NA>                  
+#> 2 1       WAKE UP 3X N                         2    NA <NA>                  
+#> 3 2       NO SLEEP   N                         1    NA <NA>                  
+#> 4 2       WAKE UP 3X Y                         2    NA <NA>                  
+#> 5 2       WAKE UP 3X Y                         3    NA <NA>                  
+#> 6 3       NO SLEEP   <NA>                      1    NA <NA>                  
+#> 7 1       WSP        No sleeping problems      2     3 Worst Sleeping Problem
+#> 8 2       WSP        Waking up three times     3     2 Worst Sleeping Problem
+#> 9 3       WSP        Missing                   1    99 Worst Sleeping Problem}\if{html}{\out{</div>}}}
+\subsection{Events based on comparison across records (\code{event_joined()})}{
+
+We'll now extend the above example. Specifically, we consider a new
+possible worst sleeping problem, namely if a subject experiences no
+sleep on consecutive days.
+\itemize{
+\item The "consecutive days" portion of the condition requires records to be
+compared with each other. This is done by using an \code{event_joined()} object,
+specifically by passing \code{dataset_name = adqs2} to it so that the \code{adqs2}
+dataset is joined onto itself. The \code{condition} now checks for two
+no sleep records, and crucially compares the \code{ADY} values to see if
+they differ by one day. The \code{.join} syntax distinguishes between the
+\code{ADY} value of the parent and joined datasets. As the condition involves
+\code{AVALC}, \code{PARAMCD} and \code{ADY}, we specify these variables with \code{join_vars},
+and finally, because we wish to compare all records with each other, we
+select \code{join_type = "all"}.
+}
+
+\if{html}{\out{<div class="sourceCode r">}}\preformatted{adqs2 <- tribble(
+   ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+   "4",      "WAKE UP",    "N",    1,
+   "4",      "NO SLEEP",   "Y",    2,
+   "4",      "NO SLEEP",   "Y",    3,
+   "5",      "NO SLEEP",   "N",    1,
+   "5",      "NO SLEEP",   "Y",    2,
+   "5",      "WAKE UP 3X", "Y",    3,
+   "5",      "NO SLEEP",   "Y",    4
+) \%>\%
+mutate(STUDYID = "AB42")
+
+derive_extreme_event(
+  adqs2,
+  by_vars = exprs(STUDYID, USUBJID),
+  events = list(
+    event_joined(
+      join_vars = exprs(AVALC, PARAMCD, ADY),
+      join_type = "all",
+      condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+        PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+        ADY == ADY.join + 1,
+      set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
     ),
     event(
-      condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-      set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+      condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+      set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+    ),
+    event(
+      condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+      set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
     ),
     event(
       condition = all(AVALC == "N"),
       set_values_to = exprs(
-        AVALC = "No sleeping problems", AVAL = 4
+        AVALC = "No sleeping problems", AVAL = 3
       )
     ),
     event(
@@ -241,37 +386,74 @@ derive_extreme_event(
   mode = "first",
   set_values_to = exprs(
     PARAMCD = "WSP",
-    PARAM = "Worst Sleeping Problems"
-  )
-)
+    PARAM = "Worst Sleeping Problem"
+  ),
+  keep_source_vars = exprs(everything())
+) \%>\%
+select(-STUDYID)
+#> # A tibble: 9 × 6
+#>   USUBJID PARAMCD    AVALC                          ADY  AVAL PARAM             
+#>   <chr>   <chr>      <chr>                        <dbl> <dbl> <chr>             
+#> 1 4       WAKE UP    N                                1    NA <NA>              
+#> 2 4       NO SLEEP   Y                                2    NA <NA>              
+#> 3 4       NO SLEEP   Y                                3    NA <NA>              
+#> 4 5       NO SLEEP   N                                1    NA <NA>              
+#> 5 5       NO SLEEP   Y                                2    NA <NA>              
+#> 6 5       WAKE UP 3X Y                                3    NA <NA>              
+#> 7 5       NO SLEEP   Y                                4    NA <NA>              
+#> 8 4       WSP        No sleep two nights in a row     3     0 Worst Sleeping Pr…
+#> 9 5       WSP        No sleep                         4     1 Worst Sleeping Pr…}\if{html}{\out{</div>}}}
+\subsection{Specifying different arguments across \code{event()} objects}{
+
+Here we consider a Hy's Law use case. We are interested in
+knowing whether a subject's Alkaline Phosphatase has ever been
+above twice the upper limit of normal range. If so, i.e. if
+\code{CRIT1FL} is \code{Y}, we are interested in the record for the first
+time this occurs, and if not, we wish to retain the last record.
+As such, for this case now we need to vary our usage of the
+\code{mode} argument dependent on the \code{event()}.
+\itemize{
+\item In first \code{event()}, since we simply seek the first time that
+\code{CRIT1FL} is \code{"Y"}, it's enough to specify the \code{condition},
+because we inherit \code{order} and \code{mode} from the main
+\code{derive_extreme_event()} call here which will automatically
+select the first occurrence by \code{AVISITN}.
+\item In the second \code{event()}, we select the last record among the
+full set of records where \code{CRIT1FL} are all \code{"N"} by additionally
+specifying \code{mode = "last"} within the \code{event()}.
+\item Note now the usage of \code{keep_source_vars = exprs(AVISITN)}
+rather than \code{everything()} as in the previous example. This
+is done to ensure \code{CRIT1} and \code{CRIT1FL} are not populated for
+the new records.
+}
 
-# Use different mode by event
-adhy <- tribble(
-  ~USUBJID, ~AVISITN, ~CRIT1FL,
-  "1",             1, "Y",
-  "1",             2, "Y",
-  "2",             1, "Y",
-  "2",             2, NA_character_,
-  "2",             3, "Y",
-  "2",             4, NA_character_
+\if{html}{\out{<div class="sourceCode r">}}\preformatted{adhy <- tribble(
+  ~USUBJID, ~AVISITN,              ~CRIT1, ~CRIT1FL,
+  "1",             1, "ALT > 2 times ULN", "N",
+  "1",             2, "ALT > 2 times ULN", "N",
+  "2",             1, "ALT > 2 times ULN", "N",
+  "2",             2, "ALT > 2 times ULN", "Y",
+  "2",             3, "ALT > 2 times ULN", "N",
+  "2",             4, "ALT > 2 times ULN", "Y"
 ) \%>\%
   mutate(
-    PARAMCD = "ALKPH",
-    PARAM = "Alkaline Phosphatase (U/L)"
+    PARAMCD = "ALT",
+    PARAM = "ALT (U/L)",
+    STUDYID = "AB42"
   )
 
 derive_extreme_event(
   adhy,
-  by_vars = exprs(USUBJID),
+  by_vars = exprs(STUDYID, USUBJID),
   events = list(
     event(
-      condition = is.na(CRIT1FL),
-      set_values_to = exprs(AVALC = "N")
+      condition = CRIT1FL == "Y",
+      set_values_to = exprs(AVALC = "Y")
     ),
     event(
-      condition = CRIT1FL == "Y",
+      condition = CRIT1FL == "N",
       mode = "last",
-      set_values_to = exprs(AVALC = "Y")
+      set_values_to = exprs(AVALC = "N")
     )
   ),
   tmp_event_nr_var = event_nr,
@@ -279,15 +461,35 @@ derive_extreme_event(
   mode = "first",
   keep_source_vars = exprs(AVISITN),
   set_values_to = exprs(
-    PARAMCD = "ALK2",
-    PARAM = "ALKPH <= 2 times ULN"
+    PARAMCD = "ALT2",
+    PARAM = "ALT > 2 times ULN"
   )
-)
-
-# Derive confirmed best overall response (using event_joined())
-# CR - complete response, PR - partial response, SD - stable disease
-# NE - not evaluable, PD - progressive disease
-adsl <- tribble(
+) \%>\%
+  select(-STUDYID)
+#> # A tibble: 8 × 7
+#>   USUBJID AVISITN CRIT1             CRIT1FL PARAMCD PARAM             AVALC
+#>   <chr>     <dbl> <chr>             <chr>   <chr>   <chr>             <chr>
+#> 1 1             1 ALT > 2 times ULN N       ALT     ALT (U/L)         <NA> 
+#> 2 1             2 ALT > 2 times ULN N       ALT     ALT (U/L)         <NA> 
+#> 3 2             1 ALT > 2 times ULN N       ALT     ALT (U/L)         <NA> 
+#> 4 2             2 ALT > 2 times ULN Y       ALT     ALT (U/L)         <NA> 
+#> 5 2             3 ALT > 2 times ULN N       ALT     ALT (U/L)         <NA> 
+#> 6 2             4 ALT > 2 times ULN Y       ALT     ALT (U/L)         <NA> 
+#> 7 1             2 <NA>              <NA>    ALT2    ALT > 2 times ULN N    
+#> 8 2             2 <NA>              <NA>    ALT2    ALT > 2 times ULN Y    }\if{html}{\out{</div>}}}
+\subsection{A more complex example: Confirmed Best Overall Response
+(\code{first/last_cond_upper}, \code{join_type}, \code{source_datasets})}{
+
+The final example showcases a use of \code{derive_extreme_event()}
+to calculate the Confirmed Best Overall Response (CBOR) in an
+\code{ADRS} dataset, as is common in many oncology trials. This example
+builds on all the previous ones and thus assumes a baseline level
+of confidence with \code{derive_extreme_event()}.
+
+The following \code{ADSL} and \code{ADRS} datasets will be used
+throughout:
+
+\if{html}{\out{<div class="sourceCode r">}}\preformatted{adsl <- tribble(
   ~USUBJID, ~TRTSDTC,
   "1",      "2020-01-01",
   "2",      "2019-12-12",
@@ -298,7 +500,10 @@ adsl <- tribble(
   "7",      "2020-02-02",
   "8",      "2020-02-01"
 ) \%>\%
-  mutate(TRTSDT = ymd(TRTSDTC))
+mutate(
+  TRTSDT = ymd(TRTSDTC),
+  STUDYID = "AB42"
+)
 
 adrs <- tribble(
   ~USUBJID, ~ADTC,        ~AVALC,
@@ -328,18 +533,60 @@ adrs <- tribble(
 ) \%>\%
   mutate(
     ADT = ymd(ADTC),
+    STUDYID = "AB42",
     PARAMCD = "OVR",
     PARAM = "Overall Response by Investigator"
   ) \%>\%
   derive_vars_merged(
     dataset_add = adsl,
-    by_vars = exprs(USUBJID),
+    by_vars = exprs(STUDYID, USUBJID),
     new_vars = exprs(TRTSDT)
-  )
+  )}\if{html}{\out{</div>}}
 
-derive_extreme_event(
+Since the CBOR derivation contains multiple complex parts, it's
+convenient to make use of the \code{description} argument within each event object
+to describe what condition is being checked.
+\itemize{
+\item For the Confirmed Response (CR), for each \code{"CR"} record in the original \code{ADRS}
+dataset that will be identified by the first part of the \code{condition} argument
+(\code{AVALC == "CR"}), we need to use the \code{first_cond_upper} argument to limit the
+group of observations to consider alongside it. Namely, we need to look up to
+and including the second CR (\code{AVALC.join == "CR"}) over 28 days from the first
+one (\code{ADT.join >= ADT + 28}). The observations satisfying \code{first_cond_upper}
+then form part of our "join group", meaning that the remaining portions of
+\code{condition} which reference joined variables are limited to this group.
+In particular, within \code{condition} we use \code{all()} to check that all observations
+are either \code{"CR"} or \code{"NE"}, and \code{count_vals()} to ensure at most one is
+\code{"NE"}.
+
+Note that the selection of \code{join_type = "after"} is critical here, due to the
+fact that the restriction implied by \code{join_type} is applied before the one
+implied by \code{first_cond_upper}. Picking the first subject (who was correctly
+identified as a confirmed responder) as an example, selecting
+\code{join_type = "all"} instead of \code{"after"} would mean the first \code{"PR"} record
+from \code{"2020-01-01"} would also be considered when evaluating the
+\code{all(AVALC.join \%in\% c("CR", "NE"))} portion of \code{condition}. In turn, the
+condition would not be satisfied anymore, and in this case, following the
+later event logic shows the subject would be considered a partial responder
+instead.
+\item The Partial Response (PR), is very similar; with the difference being that the
+first portion of \code{condition} now references \code{"PR"} and \code{first_cond_upper}
+accepts a confirmatory \code{"PR"} or \code{"CR"} 28 days later. Note that now we must add
+\code{"PR"} as an option within the \code{all()} condition to account for confirmatory
+\code{"PR"}s.
+\item The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+events are simpler and just require \code{event()} calls.
+\item Finally, we use a catch-all \code{event()} with \code{condition = TRUE} and
+\code{dataset_name = "adsl"} to identify those subjects who do not appear in \code{ADRS}
+and list their CBOR as \code{"MISSING"}. Note here the fact that \code{dataset_name} is
+set to \code{"adsl"}, which is a new source dataset. As such it's important in the
+main \code{derive_extreme_event()} call to list \code{adsl} as another source dataset
+with \code{source_datasets = list(adsl = adsl)}.
+}
+
+\if{html}{\out{<div class="sourceCode r">}}\preformatted{derive_extreme_event(
   adrs,
-  by_vars = exprs(USUBJID),
+  by_vars = exprs(STUDYID, USUBJID),
   tmp_event_nr_var = event_nr,
   order = exprs(event_nr, ADT),
   mode = "first",
@@ -352,14 +599,11 @@ derive_extreme_event(
       ),
       join_vars = exprs(AVALC, ADT),
       join_type = "after",
-      first_cond_upper = AVALC.join == "CR" &
-        ADT.join >= ADT + 28,
+      first_cond_upper = AVALC.join == "CR" & ADT.join >= ADT + 28,
       condition = AVALC == "CR" &
         all(AVALC.join \%in\% c("CR", "NE")) &
         count_vals(var = AVALC.join, val = "NE") <= 1,
-      set_values_to = exprs(
-        AVALC = "CR"
-      )
+      set_values_to = exprs(AVALC = "CR")
     ),
     event_joined(
       description = paste(
@@ -368,14 +612,11 @@ derive_extreme_event(
       ),
       join_vars = exprs(AVALC, ADT),
       join_type = "after",
-      first_cond_upper = AVALC.join \%in\% c("CR", "PR") &
-        ADT.join >= ADT + 28,
+      first_cond_upper = AVALC.join \%in\% c("CR", "PR") & ADT.join >= ADT + 28,
       condition = AVALC == "PR" &
         all(AVALC.join \%in\% c("CR", "PR", "NE")) &
         count_vals(var = AVALC.join, val = "NE") <= 1,
-      set_values_to = exprs(
-        AVALC = "PR"
-      )
+      set_values_to = exprs(AVALC = "PR")
     ),
     event(
       description = paste(
@@ -383,29 +624,21 @@ derive_extreme_event(
         "after treatment start"
       ),
       condition = AVALC \%in\% c("CR", "PR", "SD") & ADT >= TRTSDT + 28,
-      set_values_to = exprs(
-        AVALC = "SD"
-      )
+      set_values_to = exprs(AVALC = "SD")
     ),
     event(
       condition = AVALC == "PD",
-      set_values_to = exprs(
-        AVALC = "PD"
-      )
+      set_values_to = exprs(AVALC = "PD")
     ),
     event(
       condition = AVALC \%in\% c("CR", "PR", "SD", "NE"),
-      set_values_to = exprs(
-        AVALC = "NE"
-      )
+      set_values_to = exprs(AVALC = "NE")
     ),
     event(
-      description = "set response to MISSING for patients without records in ADRS",
+      description = "Set response to MISSING for patients without records in ADRS",
       dataset_name = "adsl",
       condition = TRUE,
-      set_values_to = exprs(
-        AVALC = "MISSING"
-      ),
+      set_values_to = exprs(AVALC = "MISSING"),
       keep_source_vars = exprs(TRTSDT)
     )
   ),
@@ -414,29 +647,21 @@ derive_extreme_event(
     PARAM = "Best Confirmed Overall Response by Investigator"
   )
 ) \%>\%
-  filter(PARAMCD == "CBOR")
+  filter(PARAMCD == "CBOR") \%>\%
+  select(-STUDYID, -ADTC)
+#> # A tibble: 8 × 6
+#>   USUBJID AVALC   ADT        PARAMCD PARAM                            TRTSDT    
+#>   <chr>   <chr>   <date>     <chr>   <chr>                            <date>    
+#> 1 1       CR      2020-02-01 CBOR    Best Confirmed Overall Response… 2020-01-01
+#> 2 2       SD      2020-02-01 CBOR    Best Confirmed Overall Response… 2019-12-12
+#> 3 3       MISSING NA         CBOR    Best Confirmed Overall Response… 2019-11-11
+#> 4 4       SD      2020-05-01 CBOR    Best Confirmed Overall Response… 2019-12-30
+#> 5 5       NE      2020-01-01 CBOR    Best Confirmed Overall Response… 2020-01-01
+#> 6 6       PR      2020-02-06 CBOR    Best Confirmed Overall Response… 2020-02-02
+#> 7 7       NE      2020-02-06 CBOR    Best Confirmed Overall Response… 2020-02-02
+#> 8 8       PD      2020-02-16 CBOR    Best Confirmed Overall Response… 2020-02-01}\if{html}{\out{</div>}}}
+\subsection{Further examples}{
+
+Equivalent examples for using the\code{check_type} argument can be found in
+\code{derive_extreme_records()}.}}
 
-}
-\seealso{
-\code{\link[=event]{event()}}, \code{\link[=event_joined]{event_joined()}}, \code{\link[=derive_vars_extreme_event]{derive_vars_extreme_event()}}
-
-BDS-Findings Functions for adding Parameters/Records: 
-\code{\link{default_qtc_paramcd}()},
-\code{\link{derive_expected_records}()},
-\code{\link{derive_extreme_records}()},
-\code{\link{derive_locf_records}()},
-\code{\link{derive_param_bmi}()},
-\code{\link{derive_param_bsa}()},
-\code{\link{derive_param_computed}()},
-\code{\link{derive_param_doseint}()},
-\code{\link{derive_param_exist_flag}()},
-\code{\link{derive_param_exposure}()},
-\code{\link{derive_param_framingham}()},
-\code{\link{derive_param_map}()},
-\code{\link{derive_param_qtc}()},
-\code{\link{derive_param_rr}()},
-\code{\link{derive_param_wbc_abs}()},
-\code{\link{derive_summary_records}()}
-}
-\concept{der_prm_bds_findings}
-\keyword{der_prm_bds_findings}
diff --git a/man/derive_extreme_records.Rd b/man/derive_extreme_records.Rd
index edfea640cc..ec14e3876f 100644
--- a/man/derive_extreme_records.Rd
+++ b/man/derive_extreme_records.Rd
@@ -73,8 +73,7 @@ If \code{dataset_ref} is specified, this argument must be specified.
 Within each by group the observations are ordered by the specified order.
 
 \describe{
-\item{Permitted values}{list of expressions created by \code{exprs()}, e.g.,
-\code{exprs(ADT, desc(AVAL))}}
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{none}
 }}
 
@@ -177,6 +176,7 @@ For example:
 }\if{html}{\out{</div>}}
 
 \describe{
+\item{Permitted values}{list of named expressions created by \code{exprs()}, e.g., \code{exprs(CUMDOSA = sum(AVAL, na.rm = TRUE), AVALU = "ml")}}
 \item{Default value}{none}
 }}
 }
diff --git a/man/derive_summary_records.Rd b/man/derive_summary_records.Rd
index 7707f82a94..4278b01aa1 100644
--- a/man/derive_summary_records.Rd
+++ b/man/derive_summary_records.Rd
@@ -32,6 +32,7 @@ Observations from the specified dataset are going to be used to calculate and ad
 as new records to the input dataset (\code{dataset}).
 
 \describe{
+\item{Permitted values}{a dataset, i.e., a \code{data.frame} or tibble}
 \item{Default value}{none}
 }}
 
@@ -42,6 +43,7 @@ observation of the specified dataset a new observation is added to the
 input dataset.
 
 \describe{
+\item{Permitted values}{a dataset, i.e., a \code{data.frame} or tibble}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -52,6 +54,7 @@ records. Providing the names of variables in \code{\link[=exprs]{exprs()}} will
 groupwise summary and generate summary records for the specified groups.
 
 \describe{
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{none}
 }}
 
@@ -69,6 +72,7 @@ than 2.
 }
 
 \describe{
+\item{Permitted values}{an unquoted condition, e.g., \code{AVISIT == "BASELINE"}}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -94,6 +98,7 @@ For example:
 }\if{html}{\out{</div>}}
 
 \describe{
+\item{Permitted values}{list of named expressions created by \code{exprs()}, e.g., \code{exprs(CUMDOSA = sum(AVAL, na.rm = TRUE), AVALU = "ml")}}
 \item{Default value}{none}
 }}
 
@@ -104,8 +109,7 @@ complete mapping defined by the summarization defined in \code{set_values_to}.
 specified for \code{set_values_to} can be specified for \code{missing_values}.
 
 \describe{
-\item{Permitted values}{named list of expressions, e.g.,
-\code{exprs(AVAL = -9999)}}
+\item{Permitted values}{list of named expressions created by \code{exprs()}, e.g., \code{exprs(CUMDOSA = sum(AVAL, na.rm = TRUE), AVALU = "ml")}}
 \item{Default value}{\code{NULL}}
 }}
 }
diff --git a/man/derive_var_joined_exist_flag.Rd b/man/derive_var_joined_exist_flag.Rd
index f5b24cdbab..14eb60d56b 100644
--- a/man/derive_var_joined_exist_flag.Rd
+++ b/man/derive_var_joined_exist_flag.Rd
@@ -68,7 +68,7 @@ For handling of \code{NA}s in sorting variables see \href{../articles/generic.ht
 The specified variable is added to the input dataset.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{none}
 }}
 
@@ -86,7 +86,7 @@ dataset. It can also be used to flag consecutive observations or the last
 observation (see last example below).
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/derive_var_merged_ef_msrc.Rd b/man/derive_var_merged_ef_msrc.Rd
index b68db16ff2..51dc22dd35 100644
--- a/man/derive_var_merged_ef_msrc.Rd
+++ b/man/derive_var_merged_ef_msrc.Rd
@@ -59,7 +59,7 @@ A named list of datasets is expected. The \code{dataset_name} field of
 The specified variable is added to the input dataset.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{none}
 }}
 
diff --git a/man/derive_var_merged_exist_flag.Rd b/man/derive_var_merged_exist_flag.Rd
index a3d668392d..435acf17da 100644
--- a/man/derive_var_merged_exist_flag.Rd
+++ b/man/derive_var_merged_exist_flag.Rd
@@ -47,7 +47,7 @@ The variables specified by the \code{by_vars} argument are expected.
 The specified variable is added to the input dataset.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{none}
 }}
 
diff --git a/man/derive_vars_extreme_event.Rd b/man/derive_vars_extreme_event.Rd
index b027dfa35d..dbf8fcdb1a 100644
--- a/man/derive_vars_extreme_event.Rd
+++ b/man/derive_vars_extreme_event.Rd
@@ -22,12 +22,14 @@ derive_vars_extreme_event(
 The variables specified by the \code{by_vars} and \code{order} arguments are expected to be in the dataset.
 
 \describe{
+\item{Permitted values}{a dataset, i.e., a \code{data.frame} or tibble}
 \item{Default value}{none}
 }}
 
 \item{by_vars}{Grouping variables
 
 \describe{
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/derive_vars_joined.Rd b/man/derive_vars_joined.Rd
index 15d3189bb0..406bd240e0 100644
--- a/man/derive_vars_joined.Rd
+++ b/man/derive_vars_joined.Rd
@@ -122,7 +122,7 @@ The variable is not included in the output dataset. To include it specify
 it for \code{new_vars}.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -252,7 +252,7 @@ be the value provided in \code{true_value} for all selected records from \code{d
 which are merged into the input dataset, and the value provided in \code{false_value} otherwise.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/derive_vars_merged.Rd b/man/derive_vars_merged.Rd
index 0425830fab..73822e98d1 100644
--- a/man/derive_vars_merged.Rd
+++ b/man/derive_vars_merged.Rd
@@ -131,7 +131,7 @@ be the value provided in \code{true_value} for all selected records from \code{d
 which are merged into the input dataset, and the value provided in \code{false_value} otherwise.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/filter_extreme.Rd b/man/filter_extreme.Rd
index dc109af842..f59df59210 100644
--- a/man/filter_extreme.Rd
+++ b/man/filter_extreme.Rd
@@ -12,12 +12,14 @@ filter_extreme(dataset, by_vars = NULL, order, mode, check_type = "warning")
 The variables specified by the \code{by_vars} and \code{order} arguments are expected to be in the dataset.
 
 \describe{
+\item{Permitted values}{a dataset, i.e., a \code{data.frame} or tibble}
 \item{Default value}{none}
 }}
 
 \item{by_vars}{Grouping variables
 
 \describe{
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{\code{NULL}}
 }}
 
@@ -26,8 +28,7 @@ The variables specified by the \code{by_vars} and \code{order} arguments are exp
 Within each by group the observations are ordered by the specified order.
 
 \describe{
-\item{Permitted values}{list of expressions created by \code{exprs()}, e.g.,
-\code{exprs(ADT, desc(AVAL))}}
+\item{Permitted values}{list of variables created by \code{exprs()}, e.g., \code{exprs(USUBJID, VISIT)}}
 \item{Default value}{none}
 }}
 
diff --git a/man/get_joined_data.Rd b/man/get_joined_data.Rd
index 7e0522d283..971e720e9b 100644
--- a/man/get_joined_data.Rd
+++ b/man/get_joined_data.Rd
@@ -155,7 +155,7 @@ number starts with \code{1}. The variable can be used in the conditions
 used to select consecutive observations or the last observation.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/get_joined_sub_data.Rd b/man/get_joined_sub_data.Rd
index c62308e065..7dafbe39af 100644
--- a/man/get_joined_sub_data.Rd
+++ b/man/get_joined_sub_data.Rd
@@ -58,7 +58,7 @@ number starts with \code{1}. The variable can be used in the conditions
 used to select consecutive observations or the last observation.
 
 \describe{
-\item{Permitted values}{an unquoted symbol, e.g., \code{AVAL}}
+\item{Permitted values}{a variable}
 \item{Default value}{\code{NULL}}
 }}
 
diff --git a/man/roxygen/rdx_meta.R b/man/roxygen/rdx_meta.R
index 94757fc4db..651964cd33 100644
--- a/man/roxygen/rdx_meta.R
+++ b/man/roxygen/rdx_meta.R
@@ -6,7 +6,10 @@ list(
     dataset = "a dataset, i.e., a `data.frame` or tibble",
     dataset_list = "named list of datasets, e.g., `list(adsl = adsl, ae = ae)`",
     date = "a date variable",
+    event = "an `event()` or `event_joined()` object",
     expr_list = "list of expressions created by `exprs()`, e.g., `exprs(BASEC = \"MISSING\", BASE = -1)`",
+    expr_list_formula = "list of named expressions created by a formula using `exprs()`, e.g., `exprs(AVALC = VSSTRESC, AVAL = yn_to_numeric(AVALC))`", # nolint
+    expr_list_summary = "list of named expressions created by `exprs()`, e.g., `exprs(CUMDOSA = sum(AVAL, na.rm = TRUE), AVALU = \"ml\")`",
     flag_event = "a list of `flag_event()` objects",
     join = "`\"before\"`, `\"after\"`, `\"all\"`",
     merge_rel = "`\"one-to-one\"`, `\"many-to-one\"`",
@@ -14,7 +17,7 @@ list(
     msg = "a console message to be printed, e.g. `\"Attention\"` or for longer messages use `paste(\"Line 1\", \"Line 2\")`",
     msg_type = "`\"none\"`, `\"message\"`, `\"warning\"`, `\"error\"`",
     source_list = "a list of source objects, e.g., `list(pd, death)`",
-    var = "an unquoted symbol, e.g., `AVAL`",
+    var = "a variable",
     var_list = "list of variables created by `exprs()`, e.g., `exprs(USUBJID, VISIT)`"
   )
 )


Reviews:
user: login: rossfarrugia
body: @manciniedoardo great effort! not an easy one to explain and you've done well to keep it to only 4 examples but still give enough for users to make sense of such a powerful function.
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T10:27:00Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:52:10Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:52:21Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:52:52Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:58:42Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:59:08Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:00:40Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:04:45Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:05:41Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:07:07Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:09:02Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:11:16Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T15:15:07Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T08:58:05Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:18:40Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:24:38Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:26:26Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:31:22Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:36:24Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T11:14:53Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T11:15:00Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T11:15:06Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T12:21:55Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T12:22:38Z
user: login: rossfarrugia
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-21T12:22:52Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T12:45:52Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T13:24:54Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T13:58:34Z
user: login: bundfussr
body: For me the examples are clear and well written. However, I'm already familiar with the function and the examples. Thus I'm not sure if it the same for readers who have never used the function. Maybe they would prefer simpler examples?
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T12:50:30Z
user: login: rossfarrugia
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T13:08:32Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T14:34:04Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T14:44:54Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T14:47:34Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T14:49:29Z
user: login: bundfussr
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T09:59:06Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T10:24:00Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T10:24:07Z
user: login: manciniedoardo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T10:24:19Z
user: login: bundfussr
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-23T10:35:11Z

Review comments:
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Shouldn't you also update the `@permitted` lines as part of this update too? i've been doing that as part of my examples updates, following Stefan's lead in his original PR.
created_at: 2025-05-20T08:33:28Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: some CI checks are failing and need to be resolved
created_at: 2025-05-20T08:56:22Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   (if any exist) should be identified and added as a new record, retaining
```
created_at: 2025-05-20T09:03:12Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#' @info For each subject, the observation containing the worst sleeping problem
```
created_at: 2025-05-20T09:04:48Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Minor comment but I added a dummy `STUDYID` to all my examples and used that as well in `by_vars`, as i felt like it makes them that bit more realistic, but then i dropped it from the columns shown on the page to save space. Up to you whether you want to do same or if its fine to have a variety of example conventions.
created_at: 2025-05-20T09:07:08Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   all variables from the original observation. If multiple occurrences of the
#'   worst sleeping problem occur, or no sleeping problems, then take the
#'   observation occurring at the latest day.
```
I think a little more would be useful here to reference the `desc(ADY)` usage
created_at: 2025-05-20T09:18:31Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   numbers the events consecutively. Since `mode = "first"`, we only consider
```
created_at: 2025-05-20T09:20:14Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   due to the use of the tidyselect expression `everything()`).
```
created_at: 2025-05-20T09:21:45Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: General question: Should we say in the documentation that `by_vars` is expected? FYI @bundfussr 

I tried to think of an even simpler first example looking across all subjects and without `by_vars` I got:

```
Error in `derive_extreme_event()`:
! Argument `by_vars` must be a list of <symbol>, e.g., `exprs(USUBJID, VISIT)`.
```

It doesn't seem clear that this argument is always expected to be used.
created_at: 2025-05-20T09:31:25Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: `argument` instead of `object`?
created_at: 2025-05-20T09:43:33Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'    "5",      "NO SLEEP",   "Y",    4
```
Makes a more interesting example as the no sleep events then happen more than 1 day apart and shows this subject doesnt then qualify for the consecutive days condition
created_at: 2025-05-20T09:49:06Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: I think this can be bypassed. I tried the following and it gives same result:

```
derive_extreme_event(
  adqs2,
  by_vars = exprs(USUBJID),
  events = list(
    event_joined(
      join_vars = exprs(AVALC, PARAMCD, ADY),
      join_type = "all",
      condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
        PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
        ADY == ADY.join + 1,
      set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
    ),
    event(
      condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
      set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
    ),
    event(
      condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
      set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
    ),
    event(
      condition = all(AVALC == "N"),
      set_values_to = exprs(
        AVALC = "No sleeping problems", AVAL = 3
      )
    ),
    event(
      condition = TRUE,
      set_values_to = exprs(AVALC = "Missing", AVAL = 99)
    )
  ),
  tmp_event_nr_var = event_nr,
  order = exprs(event_nr, desc(ADY)),
  mode = "first",
  set_values_to = exprs(
    PARAMCD = "WSP",
    PARAM = "Worst Sleeping Problem"
  ),
  keep_source_vars = exprs(everything())
)
```
created_at: 2025-05-20T09:50:16Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#' @info Here we consider a Hy's Law use case. We are interested in
```
created_at: 2025-05-20T09:51:54Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Instead of `ever not been below` could we say `ever been above`? reads easier to me
created_at: 2025-05-20T09:54:30Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL = "Y"` by additionally
+#'     specifying`mode = "last"` within the `event()`.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'    specifying `mode = "last"` within the `event()`.
```
created_at: 2025-05-20T09:58:12Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Could we add something extra here to explain why this is a different case, as when I first went through this i kept thinking why is this example not first as it seems the simplest? but then i caught the need to use `mode = "last"` within the event.

I'm thinking a small extra sentence like: 
```
So in this case now we need to vary our usage of the `mode` argument dependent on the `event()`.
```
created_at: 2025-05-20T10:01:43Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#' @caption Specifying different arguments across `event()` objects
```
created_at: 2025-05-20T10:02:24Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Only because of the `order` and `mode` that have been set in the `derive_extreme_event()` call itself which are taking the first occurrence by `AVISITN` here - should we clarify this? As it still needs to be applied this way by the user.
created_at: 2025-05-20T10:05:22Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL = "Y"` by additionally
+#'     specifying`mode = "last"` within the `event()`.
+#'
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: I think we should add a bullet to call out usage of `keep_source_vars = exprs(AVISITN)` here instead of the usual `exprs(everything)`, which makes sense here as you wouldn't want `CRIT1FL` populated for the new records.
created_at: 2025-05-20T10:07:40Z
author_association: COLLABORATOR
diff_hunk: @@ -331,6 +476,7 @@
 #' ) %>%
 #'   filter(PARAMCD == "CBOR")
 #'
+
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Do we need a blank line here and above?

Also we don't have a example for `check_type` around handling duplicates here - i would consider linking to stefan's `derive_extreme_records()` example here? i did similar with `derive_vars_joined()` linking to `derive_vars_merged()`. These uniqueness checks do catch out users sometimes
created_at: 2025-05-20T10:13:42Z
author_association: COLLABORATOR
diff_hunk: @@ -199,9 +319,17 @@
 #'   )
 #' )
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   ADRS dataset. This example builds on all the previous ones and
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   `ADRS` dataset. This example builds on all the previous ones and
```
Maybe also mention something like "as commonly used in oncology clinical trials"?
created_at: 2025-05-20T10:15:45Z
author_association: COLLABORATOR
diff_hunk: @@ -199,9 +319,17 @@
 #'   )
 #' )
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   ADRS dataset. This example builds on all the previous ones and
+#'   thus assumes a baseline level of confidence with
+#'   `derive_extreme_event()`.
+#'
+#'   The following ADSL and ADRS datasets will be used
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'   The following `ADSL` and `ADRS` datasets will be used
```
created_at: 2025-05-20T10:16:15Z
author_association: COLLABORATOR
diff_hunk: @@ -199,9 +319,17 @@
 #'   )
 #' )
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   ADRS dataset. This example builds on all the previous ones and
+#'   thus assumes a baseline level of confidence with
+#'   `derive_extreme_event()`.
+#'
+#'   The following ADSL and ADRS datasets will be used
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: General nice convention i feel - i see same in other places so will stop commenting this and feel free to update the other cases if you agree
created_at: 2025-05-20T10:17:11Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'     (`AVALC == "CR"`), we need to use the `first_cond_upper` argument to limit the
```
created_at: 2025-05-20T10:18:25Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Definitely best @bundfussr provides this text
created_at: 2025-05-20T10:22:23Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory PR or CR 28 days later. Note that now we must add
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'    accepts a confirmatory `"PR"` or `"CR"` 28 days later. Note that now we must add
```
created_at: 2025-05-20T10:23:00Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory PR or CR 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    PRs.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ```suggestion
#'    "`PR`"s.
```
created_at: 2025-05-20T10:23:34Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory PR or CR 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    PRs.
+#'
+#'  - The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+#'    events are simpler and just require `event()` calls.
+#'
+#'  - Finally, we use a catch-all `event()` with `condition = TRUE` and
+#'    `dataset_name = adsl` to identify those subjects who do not appear in ADRS
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Explain you also need `source_datasets = list(adsl = adsl)` in the function call as you're using a different input dataset to `dataset` for this `event()`.
created_at: 2025-05-20T10:26:02Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: you're right, done, thanks
created_at: 2025-05-20T14:52:10Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: will solve while updating
created_at: 2025-05-20T14:52:21Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: yes, agree - done thanks
created_at: 2025-05-20T14:52:51Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: It's a required argument insofar that you have to always feed an expression, but it can be empty - see this (slightly silly) example where I left `by_vars = exprs()`  and `check_type = "none"` to avoid a warning for duplicates.
```
library(tibble)
library(dplyr)
library(lubridate)

adqs1 <- tribble(
  ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
  "1",      "NO SLEEP",       "N",              1,
  "1",      "WAKE UP 3X",     "N",              2,
  "2",      "NO SLEEP",       "N",              1,
  "2",      "WAKE UP 3X",     "Y",              2,
  "2",      "WAKE UP 3X",     "Y",              3,
  "3",      "NO SLEEP",       NA_character_,    1
) %>%
mutate(STUDYID = "AB42")

derive_extreme_event(
  adqs1,
  by_vars = exprs(),
  events = list(
    event(
      condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
      set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
    ),
    event(
      condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
      set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
    ),
    event(
      condition = all(AVALC == "N"),
      set_values_to = exprs(
        AVALC = "No sleeping problems", AVAL = 3
      )
    ),
    event(
      condition = TRUE,
      set_values_to = exprs(AVALC = "Missing", AVAL = 99)
    )
  ),
  tmp_event_nr_var = event_nr,
  order = exprs(event_nr, desc(ADY)),
  mode = "first",
  set_values_to = exprs(
    PARAMCD = "WSP",
    PARAM = "Worst Sleeping Problem"
  ),
  keep_source_vars = exprs(everything()),
  check_type = "none"
) %>%
select(-STUDYID)
```
Returns:
```
# A tibble: 7 × 6
  USUBJID PARAMCD    AVALC                   ADY  AVAL PARAM                 
  <chr>   <chr>      <chr>                 <dbl> <dbl> <chr>                 
1 1       NO SLEEP   N                         1    NA NA                    
2 1       WAKE UP 3X N                         2    NA NA                    
3 2       NO SLEEP   N                         1    NA NA                    
4 2       WAKE UP 3X Y                         2    NA NA                    
5 2       WAKE UP 3X Y                         3    NA NA                    
6 3       NO SLEEP   NA                        1    NA NA                    
7 2       WSP        Waking up three times     3     2 Worst Sleeping Problem
```
Personally I don't see the need to showcase something like this because in an ADaM sense it would be very rare to look across patients.
created_at: 2025-05-20T14:58:42Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: yes, thanks
created_at: 2025-05-20T14:59:08Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: You're right, I think because in this case we already have `adqs2` as the original dataset. I'll add something different to say that it's good practice to feed in the source datasets in case they are different (see example for CBOR).
created_at: 2025-05-20T15:00:40Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: agree, will change
created_at: 2025-05-20T15:04:45Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: agree, will add
created_at: 2025-05-20T15:05:41Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL = "Y"` by additionally
+#'     specifying`mode = "last"` within the `event()`.
+#'
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: great point, will add.
created_at: 2025-05-20T15:07:07Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
+#'    object so as to indicate which dataset we wish to use for the join.
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    4
+#' )
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
 #' )
 #'
-#' # Use different mode by event
+#' @caption Specifying different arguments across `event()` object
+#' @info Here we consider a Hy's law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever not
+#'   been below twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'    time this occurs, and if not, we wish to retain the last record.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: you're right, i'd intended to explicitly say this but forgot. thanks
created_at: 2025-05-20T15:09:02Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory PR or CR 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    PRs.
+#'
+#'  - The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+#'    events are simpler and just require `event()` calls.
+#'
+#'  - Finally, we use a catch-all `event()` with `condition = TRUE` and
+#'    `dataset_name = adsl` to identify those subjects who do not appear in ADRS
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: agree, will add.
created_at: 2025-05-20T15:11:16Z
author_association: COLLABORATOR
diff_hunk: @@ -331,6 +476,7 @@
 #' ) %>%
 #'   filter(PARAMCD == "CBOR")
 #'
+
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: agree, will add a "Further examples" section
created_at: 2025-05-20T15:15:07Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ah makes sense, glad it works when empty `by_vars` are provided just in the rare case ever needed. agree though it doesn't warrant another example. i was trying to think how to break down the simplest possible first example, but as you say it wouldn't be a likely realistic usage so lets leave it as is
created_at: 2025-05-21T08:58:04Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: @manciniedoardo you missed this for some arguments: dataset, by_vars, events, tmp_event_nr_var, source_datasets, set_values_to. following Stefan's example i've been adding it to all arguments
created_at: 2025-05-21T09:18:40Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: @manciniedoardo the CBOR example at the end needs to get the following added:

```
 %>%
select(-STUDYID)
```

created_at: 2025-05-21T09:24:38Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: actually i'd also drop `ADTC` as it doesn't add anything when `ADT` is already there and its just more for the user to read
created_at: 2025-05-21T09:26:26Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = first`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   as due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
 #' library(tibble)
 #' library(dplyr)
 #' library(lubridate)
 #'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
 #' )
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
+#'   adqs1,
 #'   by_vars = exprs(USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' )
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, we also need to specify the `source_datasets`
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: ok thanks, the explanation works
created_at: 2025-05-21T09:31:22Z
author_association: COLLABORATOR
diff_hunk: @@ -199,9 +319,17 @@
 #'   )
 #' )
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   ADRS dataset. This example builds on all the previous ones and
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: @manciniedoardo there's a couple more cases of this later in the example bullets that also need to be updated
created_at: 2025-05-21T09:36:24Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: sorry, looks like i missed the inherited params - added now 🤦 
created_at: 2025-05-21T11:14:53Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject the observation containing the worst sleeping problem
+#'   (if any exist)  should be identified and added as a new record, retaining
+#'   all variables from the original observation.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: added, thanks
created_at: 2025-05-21T11:15:00Z
author_association: COLLABORATOR
diff_hunk: @@ -199,9 +319,17 @@
 #'   )
 #' )
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
+#' @info The final example showcases a use of `derive_extreme_event()`
+#'   to calculate the Confirmed Best Overall Response (CBOR) in an
+#'   ADRS dataset. This example builds on all the previous ones and
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: fixed, thanks
created_at: 2025-05-21T11:15:06Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: thanks! it's still missing for events, tmp_event_nr_var and source_datasets too which are not inherited, but then i looked at mine and Stefan's earlier PRs and noticed we missed adding it for some arguments too. i don't remember the rationale but maybe it's that we're fine to leave them out when it's very obvious from the description 🤷‍♂️ could be worth someone sanity checking all these that we've added for consistency before release, as we don't really want common arguments documented inconsistently across functions and it might just be simplest rule to have a Permitted entry for every argument.
created_at: 2025-05-21T12:21:55Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: i'll approve as from my side i'm all good with the PR, but of course this bit needs to be updated before merging
created_at: 2025-05-21T12:22:38Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +106,181 @@
 #'
 #' @export
 #'
-#' @examples
+#' @examplesx
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: Yeah i think we need to discuss as a team, but might be easiest to put permitteds everywhere. for now i will add to this PR
created_at: 2025-05-21T12:45:52Z
author_association: COLLABORATOR
diff_hunk: @@ -252,6 +380,37 @@
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original ADRS
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`) we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`. Note that here we have selected `join_type = "after"` because
+#'     <insert explanation here, explaining why join_type = "all" changes patient 1 to a "PR">.
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: I think i've got my head around this now - i've added an explanation if you'd like to check @bundfussr @rossfarrugia 
created_at: 2025-05-21T13:24:54Z
author_association: COLLABORATOR
diff_hunk: @@ -28,29 +30,53 @@
 #'
 #'   The variable is not included in the output dataset.
 #'
+#' @permitted [var]
+#'
 #' @param order Sort order
 #'
 #'   If a particular event from `events` has more than one observation, within
 #'   the event and by group, the records are ordered by the specified order.
 #'
 #'   `r roxygen_order_na_handling()`
 #'
-#' @permitted list of expressions created by `exprs()`, e.g.,
-#'   `exprs(ADT, desc(AVAL))`
+#' @permitted [var_list]
 #'
 #' @param mode Selection mode (first or last)
 #'
 #'   If a particular event from `events` has more than one observation,
 #'   `"first"`/`"last"` is used to select the first/last record of this type of
 #'   event sorting by `order`.
 #'
-#' @permitted `"first"`, `"last"`
+#' @permitted [mode]
 #'
 #' @param source_datasets Source datasets
 #'
 #'   A named list of datasets is expected. The `dataset_name` field of `event()`
 #'   and `event_joined()` refers to the dataset provided in the list.
 #'
+#' @permitted [dataset_list]
+#'
+#' @param set_values_to Variables to be set
+#'
+#'   The specified variables are set to the specified values for the new
+#'   observations.
+#'
+#'   Set a list of variables to some specified value for the new records
+#'   + LHS refer to a variable.
+#'   + RHS refers to the values to set to the variable. This can be a string, a
+#'   symbol, a numeric value, an expression or NA. If summary functions are
+#'   used, the values are summarized by the variables specified for `by_vars`.
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'   symbol, a numeric value, an expression or NA.
```
You can use summary functions but `by_vars` are not considered for summarising. So it doesn't make sense to use summary functions.
created_at: 2025-05-21T13:53:33Z
author_association: COLLABORATOR
diff_hunk: @@ -14,7 +16,8 @@ list(
     msg = "a console message to be printed, e.g. `\"Attention\"` or for longer messages use `paste(\"Line 1\", \"Line 2\")`",
     msg_type = "`\"none\"`, `\"message\"`, `\"warning\"`, `\"error\"`",
     source_list = "a list of source objects, e.g., `list(pd, death)`",
+    var_list = "list of variables created by `exprs()`, e.g., `exprs(USUBJID, VISIT)`",
     var = "a variable",
-    var_list = "list of variables created by `exprs()`, e.g., `exprs(USUBJID, VISIT)`"
+    event = "an `event()` or `event_joined()` object"
path: man/roxygen/rdx_meta.R
user: login: rossfarrugia
body: minor comment but easier to maintain if this is alphabetised
created_at: 2025-05-21T13:58:33Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
path: R/derive_extreme_event.R
user: login: bundfussr
body: I think the order is not correct. It doesn't matter for this example but it could if in `set_values_to` other variables are used.
What about the following?
```suggestion
#' - Once a record is identified as satisfying an event's condition, a new
#'   observation is created by the following process:
#'   \enumerate{
#'     \item the selected record is copied,
#'     \item the variables specified in the event's `set_values_to` (here,
#'     `AVAL` and `AVALC`) are created/updated,
#'     \item the variables specified in `keep_source_vars` (here, `ADY` does due
#'     to the use of the tidyselect expression `everything()`) (plus `by_vars`
#'     and the variables from `set_values_to`) are kept,
#'     \item the variabales specified in the global `set_values_to` (here,
#'     `PARAM` and `PARAMCD`) are created/updated.
#'   }
```
created_at: 2025-05-21T15:59:15Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'       set_values_to = exprs(AVALC = "No sleeping problems", AVAL = 3)
```
To be consistent and save some space.
created_at: 2025-05-21T16:06:49Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'  - Since we are now passing an `event_joined()` object to
```
created_at: 2025-05-21T16:33:59Z
author_association: COLLABORATOR
diff_hunk: @@ -243,18 +419,63 @@
 #' ) %>%
 #'   mutate(
 #'     ADT = ymd(ADTC),
+#'     STUDYID = "AB42",
 #'     PARAMCD = "OVR",
 #'     PARAM = "Overall Response by Investigator"
 #'   ) %>%
 #'   derive_vars_merged(
 #'     dataset_add = adsl,
-#'     by_vars = exprs(USUBJID),
+#'     by_vars = exprs(STUDYID, USUBJID),
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original `ADRS`
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`), we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`.
+#'
+#'     Note that the selection of `join_type = "after"` is critical here, due to the
+#'     fact that the restriction implied by `join_type` is applied before the one
+#'     implied by `first_cond_upper`. Picking the first subject (who was correctly
+#'     identified as a confirmed responder) as an example, selecting
+#'     `join_type = "all"` instead of `"after"` would mean the first `"PR"` record
+#'     from `"2020-01-01"` would also be considered when evaluating the
+#'     `all(AVALC.join %in% c("CR", "NE"))` portion of `condition`. In turn, the
+#'     condition would not be satisfied anymore, and in this case, following the
+#'     later event logic shows the subject would be considered a partial responder
+#'     instead.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory `"PR"` or `"CR"` 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    "`PR`"s.
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'    `"PR"`s.
```
created_at: 2025-05-21T16:54:58Z
author_association: COLLABORATOR
diff_hunk: @@ -243,18 +419,63 @@
 #' ) %>%
 #'   mutate(
 #'     ADT = ymd(ADTC),
+#'     STUDYID = "AB42",
 #'     PARAMCD = "OVR",
 #'     PARAM = "Overall Response by Investigator"
 #'   ) %>%
 #'   derive_vars_merged(
 #'     dataset_add = adsl,
-#'     by_vars = exprs(USUBJID),
+#'     by_vars = exprs(STUDYID, USUBJID),
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original `ADRS`
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`), we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`.
+#'
+#'     Note that the selection of `join_type = "after"` is critical here, due to the
+#'     fact that the restriction implied by `join_type` is applied before the one
+#'     implied by `first_cond_upper`. Picking the first subject (who was correctly
+#'     identified as a confirmed responder) as an example, selecting
+#'     `join_type = "all"` instead of `"after"` would mean the first `"PR"` record
+#'     from `"2020-01-01"` would also be considered when evaluating the
+#'     `all(AVALC.join %in% c("CR", "NE"))` portion of `condition`. In turn, the
+#'     condition would not be satisfied anymore, and in this case, following the
+#'     later event logic shows the subject would be considered a partial responder
+#'     instead.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory `"PR"` or `"CR"` 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    "`PR`"s.
+#'
+#'  - The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+#'    events are simpler and just require `event()` calls.
+#'
+#'  - Finally, we use a catch-all `event()` with `condition = TRUE` and
+#'    `dataset_name = adsl` to identify those subjects who do not appear in `ADRS`
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'    `dataset_name = "adsl"` to identify those subjects who do not appear in `ADRS`
```
created_at: 2025-05-21T16:56:25Z
author_association: COLLABORATOR
diff_hunk: @@ -243,18 +419,63 @@
 #' ) %>%
 #'   mutate(
 #'     ADT = ymd(ADTC),
+#'     STUDYID = "AB42",
 #'     PARAMCD = "OVR",
 #'     PARAM = "Overall Response by Investigator"
 #'   ) %>%
 #'   derive_vars_merged(
 #'     dataset_add = adsl,
-#'     by_vars = exprs(USUBJID),
+#'     by_vars = exprs(STUDYID, USUBJID),
 #'     new_vars = exprs(TRTSDT)
 #'   )
 #'
+#' @info Since the CBOR derivation contains multiple complex parts, it's
+#'   convenient to make use of the `description` argument within each event object
+#'   to describe what condition is being checked.
+#'
+#'   - For the Confirmed Response (CR), for each `"CR"` record in the original `ADRS`
+#'     dataset that will be identified by the first part of the `condition` argument
+#'     (`AVALC == "CR"`), we need to use the `first_cond_upper` argument to limit the
+#'     group of observations to consider alongside it. Namely, we need to look up to
+#'     and including the second CR (`AVALC.join == "CR"`) over 28 days from the first
+#'     one (`ADT.join >= ADT + 28`). The observations satisfying `first_cond_upper`
+#'     then form part of our "join group", meaning that the remaining portions of
+#'     `condition` which reference joined variables are limited to this group.
+#'     In particular, within `condition` we use `all()` to check that all observations
+#'     are either `"CR"` or `"NE"`, and `count_vals()` to ensure at most one is
+#'     `"NE"`.
+#'
+#'     Note that the selection of `join_type = "after"` is critical here, due to the
+#'     fact that the restriction implied by `join_type` is applied before the one
+#'     implied by `first_cond_upper`. Picking the first subject (who was correctly
+#'     identified as a confirmed responder) as an example, selecting
+#'     `join_type = "all"` instead of `"after"` would mean the first `"PR"` record
+#'     from `"2020-01-01"` would also be considered when evaluating the
+#'     `all(AVALC.join %in% c("CR", "NE"))` portion of `condition`. In turn, the
+#'     condition would not be satisfied anymore, and in this case, following the
+#'     later event logic shows the subject would be considered a partial responder
+#'     instead.
+#'
+#'  - The Partial Response (PR), is very similar; with the difference being that the
+#'    first portion of `condition` now references `"PR"` and `first_cond_upper`
+#'    accepts a confirmatory `"PR"` or `"CR"` 28 days later. Note that now we must add
+#'    `"PR"` as an option within the `all()` condition to account for confirmatory
+#'    "`PR`"s.
+#'
+#'  - The Stable Disease (SD), Progressive Disease (PD) and Not Evaluable (NE)
+#'    events are simpler and just require `event()` calls.
+#'
+#'  - Finally, we use a catch-all `event()` with `condition = TRUE` and
+#'    `dataset_name = adsl` to identify those subjects who do not appear in `ADRS`
+#'    and list their CBOR as `"MISSING"`. Note here the fact that `dataset_name` is
+#'    set to `adsl`, which is a new source dataset. As such it's important in the
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'    set to `"adsl"`, which is a new source dataset. As such it's important in the
```
created_at: 2025-05-21T16:57:56Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: bundfussr
body: In principle, it should be `by_vars = exprs(STUDYID, USUBJID)` because that's used in the code.

However, I would rather remove `STUDYID` from the code because it is never used or displayed. We just have additional code to add it to the data and avoid that it is displayed. I think it is unlikely that these examples are copied to be used in a study. So it doesn't matter if `STUDYID` is missing. (And even if it is used, it should be updated to `by_vars = get_admiral_option("subject_keys")`.
created_at: 2025-05-22T09:45:46Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
path: R/derive_extreme_event.R
user: login: bundfussr
body: Do we need to mention this here?

However, I like the "cross-comparison" term. Maybe we can use it in the title of the second example.
created_at: 2025-05-22T10:29:31Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
path: R/derive_extreme_event.R
user: login: bundfussr
body: What about?
```suggestion
#' @caption Events based on comparison across records (`event_joined()`)
```
created_at: 2025-05-22T10:32:26Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, it is good practice to explicitly specify the
+#'    `source_datasets` argument so as to indicate which dataset we wish to
+#'    use for the join. Note that in this case, it is not strictly needed
+#'    as even in the `event_joined()` object we are using the same source
+#'    dataset as for the general call to `derive_extreme_event()`, i.e.
+#'    `adqs2`, but this is not always the case (see the final CBOR example).
path: R/derive_extreme_event.R
user: login: bundfussr
body: I'm not sure if I would recommend this. Why should we always specify `dataset_name` for `event_joined()` but not for `event()`? Furthermore, we are not following this guidance in the CBOR example.
created_at: 2025-05-22T10:43:13Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, it is good practice to explicitly specify the
+#'    `source_datasets` argument so as to indicate which dataset we wish to
+#'    use for the join. Note that in this case, it is not strictly needed
+#'    as even in the `event_joined()` object we are using the same source
+#'    dataset as for the general call to `derive_extreme_event()`, i.e.
+#'    `adqs2`, but this is not always the case (see the final CBOR example).
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "Y",    4
+#' ) %>%
+#' mutate(STUDYID = "AB42")
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(STUDYID, USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
path: R/derive_extreme_event.R
user: login: bundfussr
body: The statement is is not wrong but in the code we set `AVALC = "Y"` if _all_ assessments were lower twice ULN. This may confuse readers.

Should we change it to setting `AVALC = "Y"` if `CRIT1FL == "Y"` like for elevated ALT?
created_at: 2025-05-22T12:24:14Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, it is good practice to explicitly specify the
+#'    `source_datasets` argument so as to indicate which dataset we wish to
+#'    use for the join. Note that in this case, it is not strictly needed
+#'    as even in the `event_joined()` object we are using the same source
+#'    dataset as for the general call to `derive_extreme_event()`, i.e.
+#'    `adqs2`, but this is not always the case (see the final CBOR example).
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "Y",    4
+#' ) %>%
+#' mutate(STUDYID = "AB42")
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(STUDYID, USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `NA`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is `NA`, it's enough to specify the `condition`,
+#'    because we inherit to `order` and `mode` from the main
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'    because we inherit `order` and `mode` from the main
```
created_at: 2025-05-22T12:25:59Z
author_association: COLLABORATOR
diff_hunk: @@ -197,11 +361,20 @@
 #'     PARAMCD = "ALK2",
 #'     PARAM = "ALKPH <= 2 times ULN"
 #'   )
-#' )
+#' ) %>%
+#' select(-STUDYID)
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
path: R/derive_extreme_event.R
user: login: bundfussr
body: Do you want to show how to derive CBOR or how to add events requiring confirmation or how `cond_first_upper`, `join_type = "after"` and `dataset_name`/`source_datasets` work?
Depending on this we may need to adjust the title.
created_at: 2025-05-22T12:43:10Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: rossfarrugia
body: Sorry that was me that requested that. I just liked the idea of seeing examples that were that bit more realistic to real studies. 
On the `get_admiral_option("subject_keys")` point, technically yes, but i seem to remember some past issue discussion when we made the templates all consistently use this that the function examples were fine to be left using hardcoded `STUDYID`, `USUBJID`. no strong opinion either way though from my side.
created_at: 2025-05-22T13:08:32Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, it is good practice to explicitly specify the
+#'    `source_datasets` argument so as to indicate which dataset we wish to
+#'    use for the join. Note that in this case, it is not strictly needed
+#'    as even in the `event_joined()` object we are using the same source
+#'    dataset as for the general call to `derive_extreme_event()`, i.e.
+#'    `adqs2`, but this is not always the case (see the final CBOR example).
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: you're right. I've just removed this bit, as we discuss this in the final section of the CBOR example anyway.
created_at: 2025-05-22T14:34:04Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
+#' - The sets of possible sleeping problems are passed through the `events`
+#'   argument as `event()` objects. Each event contains a `condition` which
+#'   may or may not be satisfied by each record (or possibly a group of
+#'   records) within the input dataset `dataset`. Summary functions such as
+#'   `any()` and `all()` are often handy to use within conditions, as is done
+#'   here for the third event, which checks that the subject had no sleeping
+#'   issues. The final event uses a catch-all `condition = TRUE` to ensure all
+#'   subjects have a new record derived. Note that in this example, as no
+#'   condition involves analysis of __cross-comparison values of within  records__,
+#'   it is sufficient to use `event()` objects rather than `event_joined()` -
+#'   see the next example for a more complex condition.
+#' - If any subject has one or more records satisfying the conditions from
+#'   events, we can select just one record using the `order` argument. In this
+#'   example, the first argument passed to `order` is `event_nr`, which is a
+#'   temporary variable created through the `tmp_event_nr_var` argument, which
+#'   numbers the events consecutively. Since `mode = "first"`, we only consider
+#'   the first event for which a condition is satisfied. Within that event, we
+#'   consider only the observation with the latest day, because the second
+#'   argument for the order is `desc(ADY)`.
+#' - Once a record is identified as satisfying an event's condition, a new
+#'   observation is created, where each variable is populated with values
+#'   sought according to the following order of precedence: (a): values
+#'   specified in the event's `set_values_to` (here, `AVAL` and `AVALC`), (b)
+#'   values specified in the global `set_values_to` (here, `PARAM` and
+#'   `PARAMCD`), (c) values from the selected observation as
+#'   long as that variable appears in `keep_source_vars` (here, `ADY` does
+#'   due to the use of the tidyselect expression `everything()`).
+#'
+#' @code
+#' library(tibble, warn.conflicts = FALSE)
+#' library(dplyr, warn.conflicts = FALSE)
+#' library(lubridate, warn.conflicts = FALSE)
+#'
+#' adqs1 <- tribble(
+#'   ~USUBJID, ~PARAMCD,         ~AVALC,        ~ADY,
+#'   "1",      "NO SLEEP",       "N",              1,
+#'   "1",      "WAKE UP 3X",     "N",              2,
+#'   "2",      "NO SLEEP",       "N",              1,
+#'   "2",      "WAKE UP 3X",     "Y",              2,
+#'   "2",      "WAKE UP 3X",     "Y",              3,
+#'   "3",      "NO SLEEP",       NA_character_,    1
+#' ) %>%
+#' mutate(STUDYID = "AB42")
 #'
-#' # Add a new record for each USUBJID storing the the worst sleeping problem.
 #' derive_extreme_event(
-#'   adqs,
-#'   by_vars = exprs(USUBJID),
+#'   adqs1,
+#'   by_vars = exprs(STUDYID, USUBJID),
 #'   events = list(
 #'     event(
 #'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
 #'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "WAKE UP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "Waking up more than three times", AVAL = 2)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
+#'     ),
+#'     event(
+#'       condition = all(AVALC == "N"),
+#'       set_values_to = exprs(
+#'         AVALC = "No sleeping problems", AVAL = 3
+#'       )
+#'     ),
+#'     event(
+#'       condition = TRUE,
+#'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
+#'     )
+#'   ),
+#'   tmp_event_nr_var = event_nr,
+#'   order = exprs(event_nr, desc(ADY)),
+#'   mode = "first",
+#'   set_values_to = exprs(
+#'     PARAMCD = "WSP",
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Add a new record for the worst observation using `event()` and
+#'    `event_joined()` objects
+#' @info We'll now extend the above example. Specifically, we consider a new
+#'    possible worst sleeping problem, namely if a subject experiences no
+#'    sleep on consecutive days.
+#'
+#'  - The "consecutive days" portion of the condition requires records to be
+#'    compared with each other. This is done by using an `event_joined()` object,
+#'    specifically by passing `dataset_name = adqs2` to it so that the `adqs2`
+#'    dataset is joined onto itself. The `condition` now checks for two
+#'    no sleep records, and crucially compares the `ADY` values to see if
+#'    they differ by one day. The `.join` syntax distinguishes between the
+#'    `ADY` value of the parent and joined datasets. As the condition involves
+#'    `AVALC`, `PARAMCD` and `ADY`, we specify these variables with `join_vars`,
+#'    and finally, because we wish to compare all records with each other, we
+#'    select `join_type = "all"`.
+#'  - Since we are now passing an `event_joined` object to
+#'    `derive_extreme_event()`, it is good practice to explicitly specify the
+#'    `source_datasets` argument so as to indicate which dataset we wish to
+#'    use for the join. Note that in this case, it is not strictly needed
+#'    as even in the `event_joined()` object we are using the same source
+#'    dataset as for the general call to `derive_extreme_event()`, i.e.
+#'    `adqs2`, but this is not always the case (see the final CBOR example).
+#'
+#' @code
+#' adqs2 <- tribble(
+#'    ~USUBJID, ~PARAMCD,     ~AVALC, ~ADY,
+#'    "4",      "WAKE UP",    "N",    1,
+#'    "4",      "NO SLEEP",   "Y",    2,
+#'    "4",      "NO SLEEP",   "Y",    3,
+#'    "5",      "NO SLEEP",   "N",    1,
+#'    "5",      "NO SLEEP",   "Y",    2,
+#'    "5",      "WAKE UP 3X", "Y",    3,
+#'    "5",      "NO SLEEP",   "Y",    4
+#' ) %>%
+#' mutate(STUDYID = "AB42")
+#'
+#' derive_extreme_event(
+#'   adqs2,
+#'   by_vars = exprs(STUDYID, USUBJID),
+#'   events = list(
+#'     event_joined(
+#'       dataset_name = "adqs2",
+#'       join_vars = exprs(AVALC, PARAMCD, ADY),
+#'       join_type = "all",
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y" &
+#'         PARAMCD.join == "NO SLEEP" & AVALC.join == "Y" &
+#'         ADY == ADY.join + 1,
+#'       set_values_to = exprs(AVALC = "No sleep two nights in a row", AVAL = 0)
+#'     ),
+#'     event(
+#'       condition = PARAMCD == "NO SLEEP" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "No sleep", AVAL = 1)
 #'     ),
 #'     event(
-#'       condition = PARAMCD == "FALL ASLEEP" & AVALC == "Y",
-#'       set_values_to = exprs(AVALC = "More than 30 mins to fall asleep", AVAL = 3)
+#'       condition = PARAMCD == "WAKE UP 3X" & AVALC == "Y",
+#'       set_values_to = exprs(AVALC = "Waking up three times", AVAL = 2)
 #'     ),
 #'     event(
 #'       condition = all(AVALC == "N"),
 #'       set_values_to = exprs(
-#'         AVALC = "No sleeping problems", AVAL = 4
+#'         AVALC = "No sleeping problems", AVAL = 3
 #'       )
 #'     ),
 #'     event(
 #'       condition = TRUE,
 #'       set_values_to = exprs(AVALC = "Missing", AVAL = 99)
 #'     )
 #'   ),
+#'   source_datasets = list(adqs2 = adqs2),
 #'   tmp_event_nr_var = event_nr,
 #'   order = exprs(event_nr, desc(ADY)),
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: Good point, I've re-jigged the example and criteria (and added a CRIT1 variable for clarity)
created_at: 2025-05-22T14:44:54Z
author_association: COLLABORATOR
diff_hunk: @@ -197,11 +361,20 @@
 #'     PARAMCD = "ALK2",
 #'     PARAM = "ALKPH <= 2 times ULN"
 #'   )
-#' )
+#' ) %>%
+#' select(-STUDYID)
 #'
-#' # Derive confirmed best overall response (using event_joined())
-#' # CR - complete response, PR - partial response, SD - stable disease
-#' # NE - not evaluable, PD - progressive disease
+#' @caption A more complex example: Confirmed Best Overall Response
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: I've added the arguments in the title, as i think it's mainly the last two options
created_at: 2025-05-22T14:47:34Z
author_association: COLLABORATOR
diff_hunk: @@ -14,7 +16,8 @@ list(
     msg = "a console message to be printed, e.g. `\"Attention\"` or for longer messages use `paste(\"Line 1\", \"Line 2\")`",
     msg_type = "`\"none\"`, `\"message\"`, `\"warning\"`, `\"error\"`",
     source_list = "a list of source objects, e.g., `list(pd, death)`",
+    var_list = "list of variables created by `exprs()`, e.g., `exprs(USUBJID, VISIT)`",
     var = "a variable",
-    var_list = "list of variables created by `exprs()`, e.g., `exprs(USUBJID, VISIT)`"
+    event = "an `event()` or `event_joined()` object"
path: man/roxygen/rdx_meta.R
user: login: manciniedoardo
body: done
created_at: 2025-05-22T14:49:29Z
author_association: COLLABORATOR
diff_hunk: @@ -156,37 +286,62 @@
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `Y`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is not `NA`, it's enough to specify the `condition`,
+#'    because we inherit `order` and `mode` from the main
+#'    `derive_extreme_event()` call here which will automatically
+#'    select the first occurrence by `AVISITN`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL` are all `NA` by additionally
+#'    specifying `mode = "last"` within the `event()`.
+#'  - Note now the usage of `keep_source_vars = exprs(AVISITN)`
+#'    rather than `everything()` as in the previous example. This
+#'    is done to ensure `CRIT1` and `CRIT1FL` are not populated for
+#'    the new records.
+#'
+#' @code
 #' adhy <- tribble(
-#'   ~USUBJID, ~AVISITN, ~CRIT1FL,
-#'   "1",             1, "Y",
-#'   "1",             2, "Y",
-#'   "2",             1, "Y",
-#'   "2",             2, NA_character_,
-#'   "2",             3, "Y",
-#'   "2",             4, NA_character_
+#'   ~USUBJID, ~AVISITN,              ~CRIT1,      ~CRIT1FL,
+#'   "1",             1, "ALT > 2 times ULN", NA_character_,
+#'   "1",             2, "ALT > 2 times ULN", NA_character_,
+#'   "2",             1, "ALT > 2 times ULN", NA_character_,
+#'   "2",             2, "ALT > 2 times ULN", "Y",
+#'   "2",             3, "ALT > 2 times ULN", NA_character_,
+#'   "2",             4, "ALT > 2 times ULN", "Y"
 #' ) %>%
 #'   mutate(
 #'     PARAMCD = "ALKPH",
-#'     PARAM = "Alkaline Phosphatase (U/L)"
path: R/derive_extreme_event.R
user: login: bundfussr
body: Should be
```
#'     PARAMCD = "ALT",
#'     PARAM = "ALT (U/L)"
```
to be consistent with `CRIT1`.
created_at: 2025-05-23T09:43:07Z
author_association: COLLABORATOR
diff_hunk: @@ -195,13 +350,23 @@
 #'   keep_source_vars = exprs(AVISITN),
 #'   set_values_to = exprs(
 #'     PARAMCD = "ALK2",
path: R/derive_extreme_event.R
user: login: bundfussr
body: ```suggestion
#'     PARAMCD = "ALT2",
```
created_at: 2025-05-23T09:43:31Z
author_association: COLLABORATOR
diff_hunk: @@ -156,37 +286,62 @@
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `Y`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is not `NA`, it's enough to specify the `condition`,
+#'    because we inherit `order` and `mode` from the main
+#'    `derive_extreme_event()` call here which will automatically
+#'    select the first occurrence by `AVISITN`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL` are all `NA` by additionally
+#'    specifying `mode = "last"` within the `event()`.
+#'  - Note now the usage of `keep_source_vars = exprs(AVISITN)`
+#'    rather than `everything()` as in the previous example. This
+#'    is done to ensure `CRIT1` and `CRIT1FL` are not populated for
+#'    the new records.
+#'
+#' @code
 #' adhy <- tribble(
-#'   ~USUBJID, ~AVISITN, ~CRIT1FL,
-#'   "1",             1, "Y",
-#'   "1",             2, "Y",
-#'   "2",             1, "Y",
-#'   "2",             2, NA_character_,
-#'   "2",             3, "Y",
-#'   "2",             4, NA_character_
+#'   ~USUBJID, ~AVISITN,              ~CRIT1,      ~CRIT1FL,
+#'   "1",             1, "ALT > 2 times ULN", NA_character_,
+#'   "1",             2, "ALT > 2 times ULN", NA_character_,
+#'   "2",             1, "ALT > 2 times ULN", NA_character_,
+#'   "2",             2, "ALT > 2 times ULN", "Y",
+#'   "2",             3, "ALT > 2 times ULN", NA_character_,
+#'   "2",             4, "ALT > 2 times ULN", "Y"
path: R/derive_extreme_event.R
user: login: bundfussr
body: This is not ADaM compliant. Either `CRIT1` should be `NA` if `CRIT1FL` is `NA` or `CRIT1FL` should be `"N"` if the criterion is not fulfilled.
created_at: 2025-05-23T09:48:11Z
author_association: COLLABORATOR
diff_hunk: @@ -106,61 +130,200 @@
 #'
 #' @export
 #'
-#' @examples
-#' library(tibble)
-#' library(dplyr)
-#' library(lubridate)
-#'
-#' adqs <- tribble(
-#'   ~USUBJID, ~PARAMCD,       ~AVALC,        ~ADY,
-#'   "1",      "NO SLEEP",     "N",              1,
-#'   "1",      "WAKE UP",      "N",              2,
-#'   "1",      "FALL ASLEEP",  "N",              3,
-#'   "2",      "NO SLEEP",     "N",              1,
-#'   "2",      "WAKE UP",      "Y",              2,
-#'   "2",      "WAKE UP",      "Y",              3,
-#'   "2",      "FALL ASLEEP",  "N",              4,
-#'   "3",      "NO SLEEP",     NA_character_,    1
-#' )
+#' @examplesx
+#'
+#' @caption Add a new record for the worst observation using `event()` objects
+#' @info For each subject, the observation containing the worst sleeping problem
+#'   (if any exist) should be identified and added as a new record, retaining
+#'   all variables from the original observation. If multiple occurrences of the
+#'   worst sleeping problem occur, or no sleeping problems, then take the
+#'   observation occurring at the latest day.
+#'
+#' - The groups for which new records are added are specified by the `by_vars`
+#'   argument. Here for each *subject* a record should be added. Thus
+#'   `by_vars = exprs(USUBJID)` is specified.
path: R/derive_extreme_event.R
user: login: bundfussr
body: @manciniedoardo , if you want to keep `STUDYID`, you should update `by_vars = exprs(USUBJID)` to `by_vars = exprs(STUDYID, USUBJID)` in the text to be consistent with the code.
created_at: 2025-05-23T09:58:38Z
author_association: COLLABORATOR
diff_hunk: @@ -156,37 +286,62 @@
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `Y`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is not `NA`, it's enough to specify the `condition`,
+#'    because we inherit `order` and `mode` from the main
+#'    `derive_extreme_event()` call here which will automatically
+#'    select the first occurrence by `AVISITN`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL` are all `NA` by additionally
+#'    specifying `mode = "last"` within the `event()`.
+#'  - Note now the usage of `keep_source_vars = exprs(AVISITN)`
+#'    rather than `everything()` as in the previous example. This
+#'    is done to ensure `CRIT1` and `CRIT1FL` are not populated for
+#'    the new records.
+#'
+#' @code
 #' adhy <- tribble(
-#'   ~USUBJID, ~AVISITN, ~CRIT1FL,
-#'   "1",             1, "Y",
-#'   "1",             2, "Y",
-#'   "2",             1, "Y",
-#'   "2",             2, NA_character_,
-#'   "2",             3, "Y",
-#'   "2",             4, NA_character_
+#'   ~USUBJID, ~AVISITN,              ~CRIT1,      ~CRIT1FL,
+#'   "1",             1, "ALT > 2 times ULN", NA_character_,
+#'   "1",             2, "ALT > 2 times ULN", NA_character_,
+#'   "2",             1, "ALT > 2 times ULN", NA_character_,
+#'   "2",             2, "ALT > 2 times ULN", "Y",
+#'   "2",             3, "ALT > 2 times ULN", NA_character_,
+#'   "2",             4, "ALT > 2 times ULN", "Y"
 #' ) %>%
 #'   mutate(
 #'     PARAMCD = "ALKPH",
-#'     PARAM = "Alkaline Phosphatase (U/L)"
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: updated thanks
created_at: 2025-05-23T10:24:00Z
author_association: COLLABORATOR
diff_hunk: @@ -195,13 +350,23 @@
 #'   keep_source_vars = exprs(AVISITN),
 #'   set_values_to = exprs(
 #'     PARAMCD = "ALK2",
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: updated thanks
created_at: 2025-05-23T10:24:07Z
author_association: COLLABORATOR
diff_hunk: @@ -156,37 +286,62 @@
 #'   mode = "first",
 #'   set_values_to = exprs(
 #'     PARAMCD = "WSP",
-#'     PARAM = "Worst Sleeping Problems"
-#'   )
-#' )
-#'
-#' # Use different mode by event
+#'     PARAM = "Worst Sleeping Problem"
+#'   ),
+#'   keep_source_vars = exprs(everything())
+#' ) %>%
+#' select(-STUDYID)
+#'
+#' @caption Specifying different arguments across `event()` objects
+#' @info Here we consider a Hy's Law use case. We are interested in
+#'   knowing whether a subject's Alkaline Phosphatase has ever been
+#'   above twice the upper limit of normal range. If so, i.e. if
+#'   `CRIT1FL` is `Y`, we are interested in the record for the first
+#'   time this occurs, and if not, we wish to retain the last record.
+#'   As such, for this case now we need to vary our usage of the
+#'   `mode` argument dependent on the `event()`.
+#'
+#'  - In first `event()`, since we simply seek the first time that
+#'    `CRIT1FL` is not `NA`, it's enough to specify the `condition`,
+#'    because we inherit `order` and `mode` from the main
+#'    `derive_extreme_event()` call here which will automatically
+#'    select the first occurrence by `AVISITN`.
+#'  - In the second `event()`, we select the last record among the
+#'    full set of records where `CRIT1FL` are all `NA` by additionally
+#'    specifying `mode = "last"` within the `event()`.
+#'  - Note now the usage of `keep_source_vars = exprs(AVISITN)`
+#'    rather than `everything()` as in the previous example. This
+#'    is done to ensure `CRIT1` and `CRIT1FL` are not populated for
+#'    the new records.
+#'
+#' @code
 #' adhy <- tribble(
-#'   ~USUBJID, ~AVISITN, ~CRIT1FL,
-#'   "1",             1, "Y",
-#'   "1",             2, "Y",
-#'   "2",             1, "Y",
-#'   "2",             2, NA_character_,
-#'   "2",             3, "Y",
-#'   "2",             4, NA_character_
+#'   ~USUBJID, ~AVISITN,              ~CRIT1,      ~CRIT1FL,
+#'   "1",             1, "ALT > 2 times ULN", NA_character_,
+#'   "1",             2, "ALT > 2 times ULN", NA_character_,
+#'   "2",             1, "ALT > 2 times ULN", NA_character_,
+#'   "2",             2, "ALT > 2 times ULN", "Y",
+#'   "2",             3, "ALT > 2 times ULN", NA_character_,
+#'   "2",             4, "ALT > 2 times ULN", "Y"
path: R/derive_extreme_event.R
user: login: manciniedoardo
body: good point updated thanks
created_at: 2025-05-23T10:24:19Z
author_association: COLLABORATOR

PR comments:
user: login: manciniedoardo
created_at: 2025-05-19T15:59:44Z
body: @rossfarrugia @bundfussr I've given this my best shot 🥲 - please review and let me know if anything is too verbose or out of place. I've found it hard to think of simple examples to this function that do not trigger most of the arguments!

Also (sorry @bundfussr I know we just talked about it but please could you help with the `join_type` explanation in CBOR? <y brain is fried and I didn't want to write something that is just wrong...!
author_association: COLLABORATOR
user: login: github-actions[bot]
created_at: 2025-05-19T16:01:01Z
body: ![Code Coverage](https://img.shields.io/badge/Code%20Coverage-98%25-success?style=flat)

Package | Line Rate | Health
-------- | --------- | ------
admiral | 98% | ✔
**Summary** | **98%** (5377 / 5482) | ✔

<!-- Sticky Pull Request Commentcode-coverage -->
author_association: CONTRIBUTOR
user: login: bundfussr
created_at: 2025-05-19T16:41:05Z
body: > @rossfarrugia @bundfussr I've given this my best shot 🥲 - please review and let me know if anything is too verbose or out of place. I've found it hard to think of simple examples to this function that do not trigger most of the arguments!
> 
> Also (sorry @bundfussr I know we just talked about it but please could you help with the `join_type` explanation in CBOR? <y brain is fried and I didn't want to write something that is just wrong...!

I wonder if we should add some simple examples to `derive_vars_joined_summary()` to demonstrate how `join_type`, `first_cond_lower`, and `first_cond_upper` work. Something like
```
> derive_vars_joined_summary(
+   mydata,
+   dataset_add = mydata,
+   order = exprs(DAY),
+   join_type = "after",
+   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
+ )
# A tibble: 5 × 2
    DAY USED_DAYS
  <dbl> <chr>    
1     1 2,3,4,5  
2     2 3,4,5    
3     3 4,5      
4     4 5        
5     5 NA       
> derive_vars_joined_summary(
+   mydata,
+   dataset_add = mydata,
+   order = exprs(DAY),
+   join_type = "after",
+   first_cond_upper = DAY.join == 4,
+   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
+ )
# A tibble: 5 × 2
    DAY USED_DAYS
  <dbl> <chr>    
1     1 2,3,4    
2     2 3,4      
3     3 4        
4     4 NA       
5     5 NA  
```
@rossfarrugia , @manciniedoardo , what do you think?
author_association: COLLABORATOR
user: login: manciniedoardo
created_at: 2025-05-20T07:23:03Z
body: > > @rossfarrugia @bundfussr I've given this my best shot 🥲 - please review and let me know if anything is too verbose or out of place. I've found it hard to think of simple examples to this function that do not trigger most of the arguments!
> > Also (sorry @bundfussr I know we just talked about it but please could you help with the `join_type` explanation in CBOR? <y brain is fried and I didn't want to write something that is just wrong...!
> 
> I wonder if we should add some simple examples to `derive_vars_joined_summary()` to demonstrate how `join_type`, `first_cond_lower`, and `first_cond_upper` work. Something like
> 
> ```
> > derive_vars_joined_summary(
> +   mydata,
> +   dataset_add = mydata,
> +   order = exprs(DAY),
> +   join_type = "after",
> +   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
> + )
> # A tibble: 5 × 2
>     DAY USED_DAYS
>   <dbl> <chr>    
> 1     1 2,3,4,5  
> 2     2 3,4,5    
> 3     3 4,5      
> 4     4 5        
> 5     5 NA       
> > derive_vars_joined_summary(
> +   mydata,
> +   dataset_add = mydata,
> +   order = exprs(DAY),
> +   join_type = "after",
> +   first_cond_upper = DAY.join == 4,
> +   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
> + )
> # A tibble: 5 × 2
>     DAY USED_DAYS
>   <dbl> <chr>    
> 1     1 2,3,4    
> 2     2 3,4      
> 3     3 4        
> 4     4 NA       
> 5     5 NA  
> ```
> 
> @rossfarrugia , @manciniedoardo , what do you think?

I think that would be nice
author_association: COLLABORATOR
user: login: bundfussr
created_at: 2025-05-20T07:26:02Z
body: > > > @rossfarrugia @bundfussr I've given this my best shot 🥲 - please review and let me know if anything is too verbose or out of place. I've found it hard to think of simple examples to this function that do not trigger most of the arguments!
> > > Also (sorry @bundfussr I know we just talked about it but please could you help with the `join_type` explanation in CBOR? <y brain is fried and I didn't want to write something that is just wrong...!
> > 
> > 
> > I wonder if we should add some simple examples to `derive_vars_joined_summary()` to demonstrate how `join_type`, `first_cond_lower`, and `first_cond_upper` work. Something like
> > ```
> > > derive_vars_joined_summary(
> > +   mydata,
> > +   dataset_add = mydata,
> > +   order = exprs(DAY),
> > +   join_type = "after",
> > +   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
> > + )
> > # A tibble: 5 × 2
> >     DAY USED_DAYS
> >   <dbl> <chr>    
> > 1     1 2,3,4,5  
> > 2     2 3,4,5    
> > 3     3 4,5      
> > 4     4 5        
> > 5     5 NA       
> > > derive_vars_joined_summary(
> > +   mydata,
> > +   dataset_add = mydata,
> > +   order = exprs(DAY),
> > +   join_type = "after",
> > +   first_cond_upper = DAY.join == 4,
> > +   new_vars = exprs(USED_DAYS = paste(DAY, collapse = ","))
> > + )
> > # A tibble: 5 × 2
> >     DAY USED_DAYS
> >   <dbl> <chr>    
> > 1     1 2,3,4    
> > 2     2 3,4      
> > 3     3 4        
> > 4     4 NA       
> > 5     5 NA  
> > ```
> > 
> > 
> >     
> >       
> >     
> > 
> >       
> >     
> > 
> >     
> >   
> > @rossfarrugia , @manciniedoardo , what do you think?
> 
> I think that would be nice

OK, I'll add them in the `derive_vars_joined_summary()` MR and then the other "joined" functions can reference them.
author_association: COLLABORATOR
user: login: manciniedoardo
created_at: 2025-05-20T15:21:06Z
body: @rossfarrugia I still need to figure out why the roxygen2 check is failing but think I have addressed everything else. Thanks for the review!
author_association: COLLABORATOR
user: login: rossfarrugia
created_at: 2025-05-21T09:05:07Z
body: > @rossfarrugia I still need to figure out why the roxygen2 check is failing but think I have addressed everything else. Thanks for the review!

No idea either. i tried from my side re-running `roxygen2::roxygenize('.')` and `devtools::document()` and there seems no changes needed. might be a CI bug, but lets see if @bundfussr spots anything when he reviews this one
author_association: COLLABORATOR
user: login: bundfussr
created_at: 2025-05-21T09:27:25Z
body: > > @rossfarrugia I still need to figure out why the roxygen2 check is failing but think I have addressed everything else. Thanks for the review!
> 
> No idea either. i tried from my side re-running `roxygen2::roxygenize('.')` and `devtools::document()` and there seems no changes needed. might be a CI bug, but lets see if @bundfussr spots anything when he reviews this one

I think the issue is that the man checks starts from scratch while in your home you usually generate the `.md` files which were changed. The conflict warning occurs only at the first `library()` call where a conflict occurs. I.e., it depends on which `.md` files are generated and the order of them.

For now, I would add `warn.conflicts = FALSE` to the library calls. Once we have implemented https://github.com/pharmaverse/admiraldev/issues/489, we could suppress the start up messages.
author_association: COLLABORATOR
user: login: manciniedoardo
created_at: 2025-05-21T13:38:32Z
body: @bundfussr @rossfarrugia ok, I think I have finally addressed everything. sorry it got a bit messy. @bundfussr please could you do a final review
author_association: COLLABORATOR
user: login: manciniedoardo
created_at: 2025-05-22T14:50:55Z
body: > For me the examples are clear and well written. However, I'm already familiar with the function and the examples. Thus I'm not sure if it the same for readers who have never used the function. Maybe they would prefer simpler examples?

@bundfussr thanks for the review - think i've addressed your comments. Personally I think the simpler examples are likely to be further from potential applications of the function to real studies, so i think it's ok to expect the user to have to do a little bit of studying to understand how this works - it's a complex function after all.
author_association: COLLABORATOR
user: login: manciniedoardo
created_at: 2025-05-23T10:52:21Z
body: ![image](https://github.com/user-attachments/assets/bdb36296-7363-4eb5-9b0d-ec6335a42754)

thanks @bundfussr @rossfarrugia for the reviews!
author_association: COLLABORATOR