From 47637a5f821d9f621af514cc0b31c2ed765bb10e Mon Sep 17 00:00:00 2001 From: ProfessorP Date: Mon, 16 Dec 2024 11:10:01 -0500 Subject: [PATCH] requested updates to documentation and test script for derive_param_tte --- NEWS.md | 4 +- R/derive_merged.R | 12 +-- R/derive_param_tte.R | 3 +- man/derive_var_merged_summary.Rd | 6 +- man/derive_vars_joined.Rd | 6 +- man/derive_vars_merged.Rd | 8 +- man/derive_vars_merged_lookup.Rd | 8 -- man/filter_date_sources.Rd | 136 +++++++++++++++++++++++++ tests/testthat/test-derive_param_tte.R | 94 ++++++++--------- 9 files changed, 201 insertions(+), 76 deletions(-) create mode 100644 man/filter_date_sources.Rd diff --git a/NEWS.md b/NEWS.md index b8bf58ddde..a840d8a1c0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,9 +12,9 @@ - Update `ADEG` template to flag `ABLFL` and `ANL01FL` based on `DTYPE == "AVERAGE"` records. (#2561) ## Updates of Existing Functions -- added `message` as option for `check_type` argument in `filter_extreme` function. (#2481) +- added `message` as option for `check_type` argument in `filter_extreme()` function. (#2481) -- Users can now specify how duplicate records are handled in `derive_param_tte` using the `check_type` argument, with options including `"error"`, `"warning"`, `"message"`, or `"none"`, allowing for greater flexibility in managing duplicate data scenarios. (#2481) +- Users can now specify how duplicate records are handled in `derive_param_tte()` using the `check_type` argument, with options including `"error"`, `"warning"`, `"message"`, or `"none"`, allowing for greater flexibility in managing duplicate data scenarios. (#2481) - `order` argument has been added to `event_source()` and `censor_source()` and defaulted to `NULL` to allow specifying variables in addition to the date variable. This can be used to ensure the uniqueness of the select records if there is more than one record per date. (#2481) diff --git a/R/derive_merged.R b/R/derive_merged.R index 9ccef85fd9..f3ce412c53 100644 --- a/R/derive_merged.R +++ b/R/derive_merged.R @@ -110,26 +110,20 @@ #' *Permitted Values*: named list of expressions, e.g., #' `exprs(BASEC = "MISSING", BASE = -1)` #' -#' -#' #' If `"warning"` or `"error"` is specified, the specified message is issued #' if the observations of the (restricted) additional dataset are not unique #' with respect to the by variables and the order. #' #' If the `order` argument is not specified, the `check_type` argument is ignored: -#' if the observations of the (restricted) additional dataset are not unique with respect -#' to the by variables, an error is issued. +#' if the observations of the (restricted) additional dataset are not unique with respect +#' to the by variables, an error is issued. #' -#' *Permitted Values*: `"none"`, `"warning"`, `"error"` -#' -#' @param check_type Check uniqueness? +#' *Permitted Values*: `"none"`,`"message"`, `"warning"`, `"error"` #' #' If `"warning"`, `"message"`, or `"error"` is specified, the specified message is issued #' if the observations of the input dataset are not unique with respect to the #' by variables and the order. #' -#' Default: `"warning"` -#' #' @param duplicate_msg Message of unique check #' #' If the uniqueness check fails, the specified message is displayed. diff --git a/R/derive_param_tte.R b/R/derive_param_tte.R index b9e788c3c0..2324b416fa 100644 --- a/R/derive_param_tte.R +++ b/R/derive_param_tte.R @@ -556,7 +556,7 @@ derive_param_tte <- function(dataset = NULL, #' @return A dataset with one observation per subject as described in the #' "Details" section. #' -#' @noRd +#' @keywords internal #' #' @examples #' library(tibble) @@ -647,7 +647,6 @@ filter_date_sources <- function(sources, { source_dataset %>% filter_if(sources[[i]]$filter) %>% - arrange(!!!sources[[i]]$order) %>% # Ensure order is applied filter_extreme( order = expr_c(exprs(!!source_date_var), sources[[i]]$order), by_vars = expr_c(subject_keys, by_vars), diff --git a/man/derive_var_merged_summary.Rd b/man/derive_var_merged_summary.Rd index bd2a2f4d8b..2263b202b7 100644 --- a/man/derive_var_merged_summary.Rd +++ b/man/derive_var_merged_summary.Rd @@ -78,7 +78,11 @@ If the \code{order} argument is not specified, the \code{check_type} argument is if the observations of the (restricted) additional dataset are not unique with respect to the by variables, an error is issued. -\emph{Permitted Values}: \code{"none"}, \code{"warning"}, \code{"error"}} +\emph{Permitted Values}: \code{"none"},\code{"message"}, \code{"warning"}, \code{"error"} + +If \code{"warning"}, \code{"message"}, or \code{"error"} is specified, the specified message is issued +if the observations of the input dataset are not unique with respect to the +by variables and the order.} } \value{ The output dataset contains all observations and variables of the diff --git a/man/derive_vars_joined.Rd b/man/derive_vars_joined.Rd index 0792f90b20..553b87172f 100644 --- a/man/derive_vars_joined.Rd +++ b/man/derive_vars_joined.Rd @@ -233,7 +233,11 @@ If the \code{order} argument is not specified, the \code{check_type} argument is if the observations of the (restricted) additional dataset are not unique with respect to the by variables, an error is issued. -\emph{Permitted Values}: \code{"none"}, \code{"warning"}, \code{"error"}} +\emph{Permitted Values}: \code{"none"},\code{"message"}, \code{"warning"}, \code{"error"} + +If \code{"warning"}, \code{"message"}, or \code{"error"} is specified, the specified message is issued +if the observations of the input dataset are not unique with respect to the +by variables and the order.} \item{check_type}{Check uniqueness? diff --git a/man/derive_vars_merged.Rd b/man/derive_vars_merged.Rd index aa18382c9c..d8b57a0c99 100644 --- a/man/derive_vars_merged.Rd +++ b/man/derive_vars_merged.Rd @@ -139,15 +139,11 @@ If the \code{order} argument is not specified, the \code{check_type} argument is if the observations of the (restricted) additional dataset are not unique with respect to the by variables, an error is issued. -\emph{Permitted Values}: \code{"none"}, \code{"warning"}, \code{"error"}} - -\item{check_type}{Check uniqueness? +\emph{Permitted Values}: \code{"none"},\code{"message"}, \code{"warning"}, \code{"error"} If \code{"warning"}, \code{"message"}, or \code{"error"} is specified, the specified message is issued if the observations of the input dataset are not unique with respect to the -by variables and the order. - -Default: \code{"warning"}} +by variables and the order.} \item{duplicate_msg}{Message of unique check diff --git a/man/derive_vars_merged_lookup.Rd b/man/derive_vars_merged_lookup.Rd index f61e11f2ad..df473ea7e2 100644 --- a/man/derive_vars_merged_lookup.Rd +++ b/man/derive_vars_merged_lookup.Rd @@ -92,14 +92,6 @@ condition. \emph{Permitted Values}: a condition} -\item{check_type}{Check uniqueness? - -If \code{"warning"}, \code{"message"}, or \code{"error"} is specified, the specified message is issued -if the observations of the input dataset are not unique with respect to the -by variables and the order. - -Default: \code{"warning"}} - \item{duplicate_msg}{Message of unique check If the uniqueness check fails, the specified message is displayed. diff --git a/man/filter_date_sources.Rd b/man/filter_date_sources.Rd new file mode 100644 index 0000000000..7736677e69 --- /dev/null +++ b/man/filter_date_sources.Rd @@ -0,0 +1,136 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/derive_param_tte.R +\name{filter_date_sources} +\alias{filter_date_sources} +\title{Select the First or Last Date from Several Sources} +\usage{ +filter_date_sources( + sources, + source_datasets, + by_vars, + create_datetime = FALSE, + subject_keys, + mode, + check_type = "none" +) +} +\arguments{ +\item{sources}{Sources + +A list of \code{tte_source()} objects is expected.} + +\item{source_datasets}{Source datasets + +A named list of datasets is expected. The \code{dataset_name} field of +\code{tte_source()} refers to the dataset provided in the list.} + +\item{by_vars}{By variables + +If the parameter is specified, for each by group the observations are +selected separately. + +\emph{Permitted Values}: list of variables created by \code{exprs()} +e.g. \code{exprs(USUBJID, VISIT)}} + +\item{create_datetime}{Create datetime variable? + +If set to \code{TRUE}, variables \code{ADTM} is created. Otherwise, variables \code{ADT} +is created.} + +\item{subject_keys}{Variables to uniquely identify a subject + +A list of symbols created using \code{exprs()} is expected.} + +\item{mode}{Selection mode (first or last) + +If \code{"first"} is specified, for each subject the first observation with +respect to the date is included in the output dataset. If \code{"last"} is +specified, the last observation is included in the output dataset. + +Permitted Values: \code{"first"}, \code{"last"} + +@param check_type Check uniqueness + +If \code{"warning"}, \code{"message"}, or \code{"error"} is specified, the specified message is issued +if the observations of the input dataset are not unique with respect to the +by variables and the order. + +Default: \code{"none"} + +Permitted Values: \code{"none"}, \code{"warning"}, \code{"error"}, \code{"message"}} +} +\value{ +A dataset with one observation per subject as described in the +"Details" section. +} +\description{ +Select for each subject the first or last observation with respect to a date +from a list of sources. +} +\details{ +The following steps are performed to create the output dataset: + +\enumerate{ \item For each source dataset the observations as specified by +the \code{filter} element are selected. Then for each patient the first or last +observation (with respect to \code{date}) is selected. + +\item The \code{ADT} variable is set to the variable specified by the +\code{date} element. If the date variable is a datetime variable, only +the datepart is copied. If the source variable is a character variable, it +is converted to a date. If the date is incomplete, it is imputed as +the first possible date. + +\item The \code{CNSR} is added and set to the value of the \code{censor} +element. + +\item The selected observations of all source datasets are combined into a +single dataset. + +\item For each patient the first or last observation (with respect to the +\code{ADT} variable) from the single dataset is selected. } +} +\examples{ +library(tibble) +library(dplyr, warn.conflicts = FALSE) +library(lubridate) + +adsl <- tribble( + ~USUBJID, ~TRTSDT, ~EOSDT, + "01", ymd("2020-12-06"), ymd("2021-03-06"), + "02", ymd("2021-01-16"), ymd("2021-02-03") +) \%>\% + mutate(STUDYID = "AB42") + +ae <- tribble( + ~USUBJID, ~AESTDTC, ~AESEQ, ~AEDECOD, + "01", "2021-01-03", 1, "Flu", + "01", "2021-03-04", 2, "Cough", + "01", "2021-01-01", 3, "Flu" +) \%>\% + mutate( + STUDYID = "AB42", + AESTDT = ymd(AESTDTC) + ) + +ttae <- event_source( + dataset_name = "ae", + date = AESTDT, + set_values_to = exprs( + EVNTDESC = "AE", + SRCDOM = "AE", + SRCVAR = "AESTDTC", + SRCSEQ = AESEQ + ) +) + +filter_date_sources( + sources = list(ttae), + source_datasets = list(adsl = adsl, ae = ae), + by_vars = exprs(AEDECOD), + create_datetime = FALSE, + subject_keys = get_admiral_option("subject_keys"), + mode = "first", + check_type = "none" +) +} +\keyword{internal} diff --git a/tests/testthat/test-derive_param_tte.R b/tests/testthat/test-derive_param_tte.R index f4c6e627e0..118f0e69ee 100644 --- a/tests/testthat/test-derive_param_tte.R +++ b/tests/testthat/test-derive_param_tte.R @@ -932,51 +932,8 @@ test_that("derive_param_tte Test 13: error if dataset_name not in source_datsets ) }) -# list_tte_source_objects ---- -## Test 14: error is issued if package does not exist ---- -test_that("list_tte_source_objects Test 14: error is issued if package does not exist", { - expect_snapshot( - list_tte_source_objects(package = "tte"), - error = TRUE - ) -}) - -## Test 15: expected objects produced ---- -test_that("list_tte_source_objects Test 15: expected objects produced", { - expected_output <- tibble::tribble( - ~object, ~dataset_name, ~filter, - "ae_ser_event", "adae", quote(TRTEMFL == "Y" & AESER == "Y"), - "ae_gr2_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "2"), - "ae_sev_event", "adae", quote(TRTEMFL == "Y" & AESEV == "SEVERE"), - "ae_gr4_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "4"), - "ae_gr3_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "3"), - "lastalive_censor", "adsl", NULL, - "ae_event", "adae", quote(TRTEMFL == "Y"), - "death_event", "adsl", quote(DTHFL == "Y"), - "ae_gr35_event", "adae", quote(TRTEMFL == "Y" & ATOXGR %in% c("3", "4", "5")), - "ae_wd_event", "adae", quote(TRTEMFL == "Y" & AEACN == "DRUG WITHDRAWN"), - "ae_gr1_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "1"), - "ae_gr5_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "5") - ) %>% - mutate( - date = case_when( - object == "lastalive_censor" ~ "LSTALVDT", - object == "death_event" ~ "DTHDT", - TRUE ~ "ASTDT" - ), - censor = if_else(object == "lastalive_censor", 1, 0), - filter = as.character(filter), - censor = as.integer(censor) - ) - - observed_output <- list_tte_source_objects(package = "admiral") %>% - select(object, dataset_name, filter, date, censor) - - expect_dfs_equal(expected_output, observed_output, keys = c("object")) -}) - -## Test 15: derive_param_tte detects duplicates when check_type = 'warning' ---- -test_that("derive_param_tte detects duplicates in the input datasets via pipeline functions", { +## Test 14: derive_param_tte detects duplicates when check_type = 'warning' ---- +test_that("derive_param_tte Test 14: detects duplicates in input datasets via pipeline functions", { # Define ADSL dataset adsl <- tibble::tribble( ~USUBJID, ~TRTSDT, ~TRTEDT, ~EOSDT, @@ -1033,8 +990,8 @@ test_that("derive_param_tte detects duplicates in the input datasets via pipelin ) }) -## Test 16: derive_param_tte produces consistent results regardless of input sort order ---- -test_that("derive_param_tte produces consistent results regardless of input sort order", { +## Test 15: derive_param_tte produces consistent results regardless of input sort order ---- +test_that("derive_param_tte Test 15: produces consistent results regardless of input sort order", { # Define ADSL dataset adsl <- tibble::tribble( ~USUBJID, ~TRTSDT, ~TRTEDT, ~EOSDT, @@ -1100,3 +1057,46 @@ test_that("derive_param_tte produces consistent results regardless of input sort expect_equal(result_sorted, result_unsorted) }) + +# list_tte_source_objects ---- +## Test 16: error is issued if package does not exist ---- +test_that("list_tte_source_objects Test 16: error is issued if package does not exist", { + expect_snapshot( + list_tte_source_objects(package = "tte"), + error = TRUE + ) +}) + +## Test 17: expected objects produced ---- +test_that("list_tte_source_objects Test 17: expected objects produced", { + expected_output <- tibble::tribble( + ~object, ~dataset_name, ~filter, + "ae_ser_event", "adae", quote(TRTEMFL == "Y" & AESER == "Y"), + "ae_gr2_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "2"), + "ae_sev_event", "adae", quote(TRTEMFL == "Y" & AESEV == "SEVERE"), + "ae_gr4_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "4"), + "ae_gr3_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "3"), + "lastalive_censor", "adsl", NULL, + "ae_event", "adae", quote(TRTEMFL == "Y"), + "death_event", "adsl", quote(DTHFL == "Y"), + "ae_gr35_event", "adae", quote(TRTEMFL == "Y" & ATOXGR %in% c("3", "4", "5")), + "ae_wd_event", "adae", quote(TRTEMFL == "Y" & AEACN == "DRUG WITHDRAWN"), + "ae_gr1_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "1"), + "ae_gr5_event", "adae", quote(TRTEMFL == "Y" & ATOXGR == "5") + ) %>% + mutate( + date = case_when( + object == "lastalive_censor" ~ "LSTALVDT", + object == "death_event" ~ "DTHDT", + TRUE ~ "ASTDT" + ), + censor = if_else(object == "lastalive_censor", 1, 0), + filter = as.character(filter), + censor = as.integer(censor) + ) + + observed_output <- list_tte_source_objects(package = "admiral") %>% + select(object, dataset_name, filter, date, censor) + + expect_dfs_equal(expected_output, observed_output, keys = c("object")) +})