diff --git a/.github/workflows/R-CMD-check.yml b/.github/workflows/R-CMD-check.yml index 30c2be2e71..1a5ed73e6a 100644 --- a/.github/workflows/R-CMD-check.yml +++ b/.github/workflows/R-CMD-check.yml @@ -3,10 +3,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel name: R-CMD-check @@ -65,7 +67,7 @@ jobs: run: | options(repos = Sys.getenv("R_REPOS")) remotes::install_deps(dependencies = TRUE) - ref <- if (Sys.getenv("GITHUB_REF_NAME") == "main") "main" else "devel" + ref <- if (Sys.getenv("GITHUB_REF_NAME") %in% c("main", "patch")) "main" else "devel" remotes::install_github( "pharmaverse/admiral.test", ref = ref, diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 40552ebf88..dc5ecea770 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -3,10 +3,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel name: Code Coverage ☂ diff --git a/.github/workflows/lintr.yaml b/.github/workflows/lintr.yaml index 9259cdb32e..d31a9effe5 100644 --- a/.github/workflows/lintr.yaml +++ b/.github/workflows/lintr.yaml @@ -3,10 +3,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel name: lint @@ -50,7 +52,6 @@ jobs: run: | if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv") renv::restore() - renv::install("lintr") shell: Rscript {0} - name: Install package diff --git a/.github/workflows/man-pages.yml b/.github/workflows/man-pages.yml index 673e7d5934..2863a77834 100644 --- a/.github/workflows/man-pages.yml +++ b/.github/workflows/man-pages.yml @@ -6,10 +6,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel issue_comment: types: [created] diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index a014678fee..55586ae919 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -6,10 +6,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel concurrency: @@ -60,7 +62,7 @@ jobs: do eval sudo $cmd done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') - + - name: Install spelling 🎓 run: | if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv") diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 4bc6b9fe1a..bdef65f579 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -6,10 +6,12 @@ on: push: branches: - main + - patch - devel pull_request: branches: - main + - patch - devel concurrency: diff --git a/DESCRIPTION b/DESCRIPTION index 8ff1126c51..5087bf3e47 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: admiral Type: Package Title: ADaM in R Asset Library -Version: 0.7.0 +Version: 0.7.1 Authors@R: c( person("Thomas", "Neitmann", email = "thomas.neitmann@roche.com", role = c("aut", "cre")), person("Stefan", "Bundfuss", role = "aut"), diff --git a/NEWS.md b/NEWS.md index 3d451ede96..5c9c6a415b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,18 @@ +# admiral 0.7.1 + +- `derive_vars_last_dose()` no longer fails when a variable renamed in `new_vars` is supplied +to the `dose_date` parameter (#1206) + +- `derive_vars_duration()` updated to not display units when there is missing +duration (#1207) + +- `derive_param_first_event()` was updated (#1214) such that + - `AVAL` is derived instead of `AVALN` and + - all variables from the source dataset are kept. + +- `slice_derivation()` was updated such that it no longer fails if a slice is +empty (#1309) + # admiral 0.7.0 ## New Features diff --git a/R/derive_param_first_event.R b/R/derive_param_first_event.R index a4a0e3e172..dfa282db80 100644 --- a/R/derive_param_first_event.R +++ b/R/derive_param_first_event.R @@ -73,6 +73,9 @@ #' subjects with event `AVALC` is set to `"Y"`, `AVAL` to `1`, and `ADT` to #' the first date where the event condition is fulfilled. For all other #' subjects `AVALC` is set to `"N"`, `AVAL` to `0`, and `ADT` to `NA`. +#' For subjects with event all variables from `dataset_source` are kept. For +#' subjects without event all variables which are in both `dataset_adsl` and +#' `dataset_source` are kept. #' 1. The variables specified by the `set_values_to` parameter are added to #' the new observations. #' 1. The new observations are added to input dataset. @@ -169,19 +172,26 @@ derive_param_first_event <- function(dataset, assert_param_does_not_exist(dataset, quo_get_expr(set_values_to$PARAMCD)) # Create new observations - new_obs <- derive_vars_merged( - select(dataset_adsl, !!!subject_keys), - dataset_add = dataset_source, - filter_add = !!filter_source, - by_vars = subject_keys, - order = vars(!!date_var), - new_vars = vars(ADT = !!date_var), - mode = "first", - check_type = check_type - ) %>% + source_vars <- colnames(dataset_source) + adsl_vars <- colnames(dataset_adsl) + + events <- dataset_source %>% + filter_if(filter_source) %>% + filter_extreme( + by_vars = subject_keys, + order = vars(!!date_var), + mode = "first", + check_type = check_type + ) + noevents <- anti_join( + select(dataset_adsl, intersect(source_vars, adsl_vars)), + select(events, !!!subject_keys) + ) + new_obs <- bind_rows(events, noevents) %>% mutate( + ADT = !!date_var, AVALC = if_else(!is.na(ADT), "Y", "N"), - AVALN = if_else(!is.na(ADT), 1, 0), + AVAL = if_else(!is.na(ADT), 1, 0), !!!set_values_to ) diff --git a/R/derive_var_ontrtfl.R b/R/derive_var_ontrtfl.R index 26f3b1996e..1475af8360 100644 --- a/R/derive_var_ontrtfl.R +++ b/R/derive_var_ontrtfl.R @@ -92,10 +92,11 @@ #' @export #' #' @examples +#' library(tibble) #' library(dplyr) #' library(lubridate, warn.conflict = FALSE) #' -#' advs <- tibble::tribble( +#' advs <- tribble( #' ~USUBJID, ~ADT, ~TRTSDT, ~TRTEDT, #' "P01", ymd("2020-02-24"), ymd("2020-01-01"), ymd("2020-03-01"), #' "P02", ymd("2020-01-01"), ymd("2020-01-01"), ymd("2020-03-01"), @@ -108,7 +109,7 @@ #' ref_end_date = TRTEDT #' ) #' -#' advs <- tibble::tribble( +#' advs <- tribble( #' ~USUBJID, ~ADT, ~TRTSDT, ~TRTEDT, #' "P01", ymd("2020-07-01"), ymd("2020-01-01"), ymd("2020-03-01"), #' "P02", ymd("2020-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), @@ -122,11 +123,11 @@ #' ref_end_window = 60 #' ) #' -#' advs <- tibble::tribble( -#' ~USUBJID, ~ADTM, ~TRTSDTM, ~TRTEDTM, -#' "P01", ymd("2020-01-02T12:00"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), -#' "P02", ymd("2020-01-01"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), -#' "P03", ymd("2019-12-31"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), +#' advs <- tribble( +#' ~USUBJID, ~ADTM, ~TRTSDTM, ~TRTEDTM, +#' "P01", ymd_hm("2020-01-02T12:00"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), +#' "P02", ymd("2020-01-01"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), +#' "P03", ymd("2019-12-31"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), #' ) %>% #' mutate(TPT = c(NA, "PRE", NA)) #' derive_var_ontrtfl( @@ -137,7 +138,7 @@ #' filter_pre_timepoint = TPT == "PRE" #' ) #' -#' advs <- tibble::tribble( +#' advs <- tribble( #' ~USUBJID, ~ASTDT, ~TRTSDT, ~TRTEDT, ~AENDT, #' "P01", ymd("2020-03-15"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-12-01"), #' "P02", ymd("2019-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-03-15"), @@ -153,7 +154,7 @@ #' span_period = "Y" #' ) #' -#' advs <- tibble::tribble( +#' advs <- tribble( #' ~USUBJID, ~ASTDT, ~AP01SDT, ~AP01EDT, ~AENDT, #' "P01", ymd("2020-03-15"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-12-01"), #' "P02", ymd("2019-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-03-15"), diff --git a/R/derive_vars_duration.R b/R/derive_vars_duration.R index c7cdfcfedc..5d0260a81b 100644 --- a/R/derive_vars_duration.R +++ b/R/derive_vars_duration.R @@ -86,9 +86,15 @@ #' @seealso [compute_duration()] #' #' @examples -#' data <- tibble::tribble( +#' library(lubridate) +#' library(tibble) +#' +#' data <- tribble( #' ~BRTHDT, ~RANDDT, -#' lubridate::ymd("1984-09-06"), lubridate::ymd("2020-02-24") +#' ymd("1984-09-06"), ymd("2020-02-24"), +#' ymd("1985-01-01"), NA, +#' NA, ymd("2021-03-10"), +#' NA, NA #' ) #' #' derive_vars_duration(data, @@ -143,7 +149,8 @@ derive_vars_duration <- function(dataset, ) if (!quo_is_null(new_var_unit)) { - dataset <- dataset %>% mutate(!!new_var_unit := toupper(out_unit)) + dataset <- dataset %>% + mutate(!!new_var_unit := if_else(is.na(!!new_var), NA_character_, toupper(out_unit))) } dataset diff --git a/R/derive_vars_last_dose.R b/R/derive_vars_last_dose.R index 06a61acccf..66e2169d2f 100644 --- a/R/derive_vars_last_dose.R +++ b/R/derive_vars_last_dose.R @@ -1,26 +1,36 @@ #' Derive Last Dose #' #' Add EX source variables from last dose to the input dataset. +#' #' @param dataset Input dataset. #' The variables specified by the `by_vars` and `analysis_date` parameters are expected. +#' #' @param dataset_ex Input EX dataset. #' The variables specified by the `by_vars`, `dose_date`, `new_vars` parameters, #' and source variables from `traceability_vars` parameter are expected. +#' #' @param filter_ex Filtering condition applied to EX dataset. #' For example, it can be used to filter for valid dose. #' Defaults to NULL. +#' #' @param by_vars Variables to join by (created by `dplyr::vars`). +#' #' @param dose_id Variables to identify unique dose (created by `dplyr::vars`). #' Defaults to empty `vars()`. +#' #' @param new_vars Variables to keep from `dataset_ex`, with the option to rename. Can either #' be variables created by `dplyr::vars` (e.g. `vars(VISIT)`), or named list returned by [`vars()`] #' (e.g. `vars(LSTEXVIS = VISIT)`). If set to `NULL`, then all variables from `dataset_ex` are #' kept without renaming. #' Defaults to `NULL`. +#' #' @param dose_date The EX dose date variable. A date or date-time object is expected. +#' #' @param analysis_date The analysis date variable. A date or date-time object is expected. +#' #' @param single_dose_condition The condition for checking if `dataset_ex` is single dose. An error #' is issued if the condition is not true. Defaults to `(EXDOSFRQ == "ONCE")`. +#' #' @param traceability_vars A named list returned by [`vars()`] listing the traceability variables, #' e.g. `vars(LDOSEDOM = "EX", LDOSESEQ = EXSEQ)`. #' The left-hand side (names of the list elements) gives the names of the traceability variables @@ -29,7 +39,8 @@ #' in the returned dataset. #' These can be either strings or symbols referring to existing variables. #' -#' @details All date (date-time) variables can be characters in standard ISO format or +#' @details +#' All date (date-time) variables can be characters in standard ISO format or #' of date / date-time class. #' For ISO format, see [`impute_dtc`] - parameter `dtc` for further details. #' When doing date comparison to identify last dose, date-time imputations are done as follows: @@ -37,6 +48,7 @@ #' * `analysis_date`: no date imputation, time imputation to `23:59:59` if time is missing. #' #' The last dose records are identified as follows: +#' #' 1. The `dataset_ex` is filtered using `filter_ex`, if provided. #' This is useful for, for example, filtering for valid dose only. #' 2. The datasets `dataset` and `dataset_ex` are joined using `by_vars`. @@ -52,9 +64,9 @@ #' `dataset` and returned to the user. #' #' This function only works correctly for EX dataset with a structure of single dose per row. -#' If your study EX dataset has multiple doses per row, use `expansion_function_name??` to +#' If your study EX dataset has multiple doses per row, use [`create_single_dose_dataset()`] to #' transform the EX dataset into single dose per row structure before calling -#' `derive_vars_last_dose`. +#' `derive_vars_last_dose()`. #' #' If variables (other than those specified in `by_vars`) exist in both `dataset` and `dataset_ex`, #' then join cannot be performed properly and an error is issued. To resolve the error, use @@ -109,7 +121,7 @@ derive_vars_last_dose <- function(dataset, dose_id = vars(), dose_date, analysis_date, - single_dose_condition = (EXDOSFRQ == "ONCE"), + single_dose_condition = EXDOSFRQ == "ONCE", new_vars = NULL, traceability_vars = NULL) { filter_ex <- assert_filter_cond(enquo(filter_ex), optional = TRUE) @@ -121,10 +133,12 @@ derive_vars_last_dose <- function(dataset, assert_varval_list(new_vars, optional = TRUE, accept_var = TRUE) assert_varval_list(traceability_vars, optional = TRUE) assert_data_frame(dataset, quo_c(by_vars, analysis_date)) - assert_data_frame(dataset_ex, quo_c( - by_vars, dose_date, new_vars, - get_source_vars(traceability_vars) - )) + if (as_name(dose_date) %in% names(new_vars)) { + required_vars <- quo_c(by_vars, new_vars, get_source_vars(traceability_vars)) + } else { + required_vars <- quo_c(by_vars, dose_date, new_vars, get_source_vars(traceability_vars)) + } + assert_data_frame(dataset_ex, required_vars) # vars converted to string by_vars_str <- vars2chr(by_vars) @@ -136,15 +150,22 @@ derive_vars_last_dose <- function(dataset, all() if (!single_dose_eval) { - stop("Specified single_dose_condition is not satisfied.") + stop("Specified `single_dose_condition` is not satisfied.") } - # check if doses are unique based on dose_date and dose_id + # check if doses are unique based on `dose_date` and `dose_id` + if (as_name(dose_date) %in% names(new_vars)) { + unique_by <- c(by_vars, new_vars[[as_name(dose_date)]], dose_id) + } else { + unique_by <- c(by_vars, dose_date, dose_id) + } signal_duplicate_records( - dataset_ex, c(by_vars, dose_date, dose_id), - "Multiple doses exist for the same dose_date. Update dose_id to identify unique doses." + dataset_ex, + unique_by, + "Multiple doses exist for the same `dose_date`. Update `dose_id` to identify unique doses." ) + # filter EX based on user-specified condition if (!is.null(quo_get_expr(filter_ex))) { dataset_ex <- dataset_ex %>% diff --git a/R/slice_derivation.R b/R/slice_derivation.R index 8492503bf4..0ae215956e 100644 --- a/R/slice_derivation.R +++ b/R/slice_derivation.R @@ -114,11 +114,14 @@ slice_derivation <- function(dataset, call <- as.call(c(substitute(derivation), c(quote(data), act_args, slices[[i]]$args))) obsnr <- which(dataset_split$temp_slicenr == i) - dataset_split$data[[obsnr]] <- - eval(call, envir = list( - data = dataset_split$data[[obsnr]], - enclos = parent.frame() - )) + if (length(obsnr) > 0) { + # call the derivation for non-empty slices only + dataset_split$data[[obsnr]] <- + eval(call, envir = list( + data = dataset_split$data[[obsnr]], + enclos = parent.frame() + )) + } } # put datasets together again diff --git a/man/derive_param_first_event.Rd b/man/derive_param_first_event.Rd index 8d6e24c867..edfc6f5fc6 100644 --- a/man/derive_param_first_event.Rd +++ b/man/derive_param_first_event.Rd @@ -95,6 +95,9 @@ fulfilled is selected. subjects with event \code{AVALC} is set to \code{"Y"}, \code{AVAL} to \code{1}, and \code{ADT} to the first date where the event condition is fulfilled. For all other subjects \code{AVALC} is set to \code{"N"}, \code{AVAL} to \code{0}, and \code{ADT} to \code{NA}. +For subjects with event all variables from \code{dataset_source} are kept. For +subjects without event all variables which are in both \code{dataset_adsl} and +\code{dataset_source} are kept. \item The variables specified by the \code{set_values_to} parameter are added to the new observations. \item The new observations are added to input dataset. diff --git a/man/derive_var_ontrtfl.Rd b/man/derive_var_ontrtfl.Rd index 4519d54d7c..8e9b52e95a 100644 --- a/man/derive_var_ontrtfl.Rd +++ b/man/derive_var_ontrtfl.Rd @@ -107,10 +107,11 @@ If the \code{span_period} is specified as \code{"Y"}, this allows the user to as Any date imputations needed should be done prior to calling this function. } \examples{ +library(tibble) library(dplyr) library(lubridate, warn.conflict = FALSE) -advs <- tibble::tribble( +advs <- tribble( ~USUBJID, ~ADT, ~TRTSDT, ~TRTEDT, "P01", ymd("2020-02-24"), ymd("2020-01-01"), ymd("2020-03-01"), "P02", ymd("2020-01-01"), ymd("2020-01-01"), ymd("2020-03-01"), @@ -123,7 +124,7 @@ derive_var_ontrtfl( ref_end_date = TRTEDT ) -advs <- tibble::tribble( +advs <- tribble( ~USUBJID, ~ADT, ~TRTSDT, ~TRTEDT, "P01", ymd("2020-07-01"), ymd("2020-01-01"), ymd("2020-03-01"), "P02", ymd("2020-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), @@ -137,11 +138,11 @@ derive_var_ontrtfl( ref_end_window = 60 ) -advs <- tibble::tribble( - ~USUBJID, ~ADTM, ~TRTSDTM, ~TRTEDTM, - "P01", ymd("2020-01-02T12:00"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), - "P02", ymd("2020-01-01"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), - "P03", ymd("2019-12-31"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), +advs <- tribble( + ~USUBJID, ~ADTM, ~TRTSDTM, ~TRTEDTM, + "P01", ymd_hm("2020-01-02T12:00"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), + "P02", ymd("2020-01-01"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), + "P03", ymd("2019-12-31"), ymd_hm("2020-01-01T12:00"), ymd_hm("2020-03-01T12:00"), ) \%>\% mutate(TPT = c(NA, "PRE", NA)) derive_var_ontrtfl( @@ -152,7 +153,7 @@ derive_var_ontrtfl( filter_pre_timepoint = TPT == "PRE" ) -advs <- tibble::tribble( +advs <- tribble( ~USUBJID, ~ASTDT, ~TRTSDT, ~TRTEDT, ~AENDT, "P01", ymd("2020-03-15"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-12-01"), "P02", ymd("2019-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-03-15"), @@ -168,7 +169,7 @@ derive_var_ontrtfl( span_period = "Y" ) -advs <- tibble::tribble( +advs <- tribble( ~USUBJID, ~ASTDT, ~AP01SDT, ~AP01EDT, ~AENDT, "P01", ymd("2020-03-15"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-12-01"), "P02", ymd("2019-04-30"), ymd("2020-01-01"), ymd("2020-03-01"), ymd("2020-03-15"), diff --git a/man/derive_vars_duration.Rd b/man/derive_vars_duration.Rd index e707bdfbdd..444fcebf05 100644 --- a/man/derive_vars_duration.Rd +++ b/man/derive_vars_duration.Rd @@ -99,9 +99,15 @@ is negative. The start and end date variable must be present in the specified input dataset. } \examples{ -data <- tibble::tribble( +library(lubridate) +library(tibble) + +data <- tribble( ~BRTHDT, ~RANDDT, - lubridate::ymd("1984-09-06"), lubridate::ymd("2020-02-24") + ymd("1984-09-06"), ymd("2020-02-24"), + ymd("1985-01-01"), NA, + NA, ymd("2021-03-10"), + NA, NA ) derive_vars_duration(data, diff --git a/man/derive_vars_last_dose.Rd b/man/derive_vars_last_dose.Rd index f1d963d11a..2f3b857ae7 100644 --- a/man/derive_vars_last_dose.Rd +++ b/man/derive_vars_last_dose.Rd @@ -12,7 +12,7 @@ derive_vars_last_dose( dose_id = vars(), dose_date, analysis_date, - single_dose_condition = (EXDOSFRQ == "ONCE"), + single_dose_condition = EXDOSFRQ == "ONCE", new_vars = NULL, traceability_vars = NULL ) @@ -89,9 +89,9 @@ sorted by \code{dose_id} will be used to identify last dose. } This function only works correctly for EX dataset with a structure of single dose per row. -If your study EX dataset has multiple doses per row, use \verb{expansion_function_name??} to +If your study EX dataset has multiple doses per row, use \code{\link[=create_single_dose_dataset]{create_single_dose_dataset()}} to transform the EX dataset into single dose per row structure before calling -\code{derive_vars_last_dose}. +\code{derive_vars_last_dose()}. If variables (other than those specified in \code{by_vars}) exist in both \code{dataset} and \code{dataset_ex}, then join cannot be performed properly and an error is issued. To resolve the error, use diff --git a/tests/testthat/test-derive_param_first_event.R b/tests/testthat/test-derive_param_first_event.R index a19ce0b9f0..eb978f3fa3 100644 --- a/tests/testthat/test-derive_param_first_event.R +++ b/tests/testthat/test-derive_param_first_event.R @@ -47,7 +47,7 @@ test_that("derive_param_first_event Test 1: derive first PD date", { expected <- bind_rows( adrs, tibble::tribble( - ~USUBJID, ~ADT, ~AVALC, ~AVALN, + ~USUBJID, ~ADT, ~AVALC, ~AVAL, "1", ymd(""), "N", 0, "2", ymd("2021-07-16"), "Y", 1, "3", ymd(""), "N", 0 @@ -83,10 +83,10 @@ test_that("derive_param_first_event Test 2: derive death date parameter", { expected <- bind_rows( adrs, tibble::tribble( - ~USUBJID, ~ADT, ~AVALC, ~AVALN, - "1", ymd("2022-05-13"), "Y", 1, - "2", ymd(""), "N", 0, - "3", ymd(""), "N", 0 + ~USUBJID, ~ADT, ~AVALC, ~AVAL, ~DTHDT, + "1", ymd("2022-05-13"), "Y", 1, ymd("2022-05-13"), + "2", ymd(""), "N", 0, ymd(""), + "3", ymd(""), "N", 0, ymd("") ) %>% mutate( STUDYID = "XX1234", diff --git a/tests/testthat/test-derive_duration.R b/tests/testthat/test-derive_vars_duration.R similarity index 55% rename from tests/testthat/test-derive_duration.R rename to tests/testthat/test-derive_vars_duration.R index 79e725f45d..c29c499ac6 100644 --- a/tests/testthat/test-derive_duration.R +++ b/tests/testthat/test-derive_vars_duration.R @@ -1,9 +1,15 @@ +library(tibble) +library(lubridate) + test_that("duration and unit variable are added", { - input <- tibble::tribble( + input <- tribble( ~BRTHDT, ~RANDDT, - ymd("1999-09-09"), ymd("2020-02-20") + ymd("1984-09-06"), ymd("2020-02-24"), + ymd("1985-01-01"), NA, + NA, ymd("2021-03-10"), + NA, NA ) - expected_output <- mutate(input, AGE = 20, AGEU = "YEARS") + expected_output <- mutate(input, AGE = c(35, NA, NA, NA), AGEU = c("YEARS", NA, NA, NA)) actual_output <- derive_vars_duration( input, new_var = AGE, diff --git a/tests/testthat/test-derive_vars_last_dose.R b/tests/testthat/test-derive_vars_last_dose.R index 13a3a642a8..949c236940 100644 --- a/tests/testthat/test-derive_vars_last_dose.R +++ b/tests/testthat/test-derive_vars_last_dose.R @@ -22,7 +22,7 @@ input_ex <- tibble::tribble( mutate(EXSTDTC = as.Date(EXSTDTC), EXENDTC = as.Date(EXENDTC)) -test_that("derive_vars_last_dose works as expected", { +test_that("derive_vars_last_dose Test 1: function works as expected", { expected_output <- mutate( input_ae, EXSTDTC = as.Date(c("2020-01-01", "2020-08-29", "2020-09-02", NA, "2020-01-20", NA, NA)), @@ -48,7 +48,7 @@ test_that("derive_vars_last_dose works as expected", { }) -test_that("derive_vars_last_dose checks validity of start and end dose inputs", { +test_that("derive_vars_last_dose Test 2: function checks validity of start and end dose inputs", { input_ex_wrong <- dplyr::bind_rows( input_ex, tibble::tribble( @@ -68,12 +68,12 @@ test_that("derive_vars_last_dose checks validity of start and end dose inputs", single_dose_condition = (EXSTDTC == EXENDTC), traceability_vars = NULL ), - regexp = "Specified single_dose_condition is not satisfied." + regexp = "Specified `single_dose_condition` is not satisfied." ) }) -test_that("derive_vars_last_dose returns traceability vars", { +test_that("derive_vars_last_dose Test 3: function returns traceability vars", { expected_output <- mutate( input_ae, EXSTDTC = as.Date(c("2020-01-01", "2020-08-29", "2020-09-02", NA, "2020-01-20", NA, NA)), @@ -101,7 +101,7 @@ test_that("derive_vars_last_dose returns traceability vars", { }) -test_that("derive_vars_last_dose when multiple doses on same date - error", { +test_that("derive_vars_last_dose Test 4: function errors when multiple doses are on same date", { input_ex_dup <- dplyr::bind_rows( input_ex, tibble::tribble( @@ -130,12 +130,12 @@ test_that("derive_vars_last_dose when multiple doses on same date - error", { single_dose_condition = (EXSTDTC == EXENDTC), traceability_vars = NULL ), - regexp = "Multiple doses exist for the same dose_date. Update dose_id to identify unique doses." + regexp = "Multiple doses exist for the same `dose_date`. Update `dose_id` to identify unique doses." # nolint ) }) -test_that("derive_vars_last_dose when multiple doses on same date - dose_id supplied", { +test_that("derive_vars_last_dose Test 5: multiple doses on same date - dose_id supplied", { input_ex_dup <- dplyr::bind_rows( input_ex, tibble::tribble( @@ -170,7 +170,7 @@ test_that("derive_vars_last_dose when multiple doses on same date - dose_id supp }) -test_that("derive_vars_last_dose - Error is issued if same variable is found in both input datasets ", { # nolint +test_that("derive_vars_last_dose Test 6: error is issued if same variable is found in both input datasets ", { # nolint input_ae <- tibble::tribble( ~STUDYID, ~USUBJID, ~AESEQ, ~EXSTDTC, "my_study", "subject1", 1, "2020-01-02", @@ -210,3 +210,32 @@ test_that("derive_vars_last_dose - Error is issued if same variable is found in fixed = TRUE ) }) + +test_that("derive_vars_last_dose Test 7: no error is raised when setting `dose_date` to a renamed variable", { # nolint + adae <- tibble::tribble( + ~USUBJID, ~AESTDTC, ~AENDTC, ~ASTDT, ~AENDT, ~AEDECOD, + "P01", "2022-01-10", "2022-01-12", ymd("2022-01-10"), ymd("2022-01-12"), "Nausea", + "P02", "2022-01-31", "2022-01-31", ymd("2022-01-31"), ymd("2022-01-31"), "Vomitting", + "P02", "2022-02-02", "2022-02-04", ymd("2022-02-02"), ymd("2022-02-04"), "Vomitting" + ) + + adex <- tibble::tribble( + ~USUBJID, ~EXTRT, ~EXDOSFRQ, ~EXSTDTC, ~EXENDTC, ~ASTDT, ~AENDT, + "P01", "Drug A", "QD", "2022-01-09", "2022-01-12", ymd("2022-01-09"), ymd("2022-01-12"), + "P02", "Drug A", "QD", "2022-02-01", "2022-02-04", ymd("2022-02-01"), ymd("2022-02-04") + ) + + (adex_single <- create_single_dose_dataset(adex)) + + expect_error( + derive_vars_last_dose( + adae, + adex_single, + by_vars = vars(USUBJID), + dose_date = EXSTDT, + analysis_date = AESTDTC, + new_vars = vars(EXSTDT = ASTDT) + ), + NA + ) +}) diff --git a/tests/testthat/test-slice_derivation.R b/tests/testthat/test-slice_derivation.R index fe61eefa22..6d3784f06f 100644 --- a/tests/testthat/test-slice_derivation.R +++ b/tests/testthat/test-slice_derivation.R @@ -1,5 +1,5 @@ # slice_derivation ---- -## slice_derivation Test 1: slice derivation ---- +## Test 1: slice derivation ---- test_that("slice_derivation Test 1: slice derivation", { advs <- tibble::tribble( ~USUBJID, ~VSDTC, ~VSTPT, ~VSSEQ, @@ -36,7 +36,7 @@ test_that("slice_derivation Test 1: slice derivation", { ) }) -## slice_derivation Test 2: non matching observations ---- +## Test 2: non matching observations ---- test_that("slice_derivation Test 2: non matching observations", { advs <- tibble::tribble( ~USUBJID, ~VSDTC, ~VSTPT, ~VSSEQ, @@ -57,7 +57,8 @@ test_that("slice_derivation Test 2: non matching observations", { ) ) - expected <- mutate(advs, + expected <- mutate( + advs, ADTM = c(ymd_hms(NA), ymd_hms("2020-04-16 00:00:00")), ATMF = c(NA_character_, "H") ) @@ -69,8 +70,46 @@ test_that("slice_derivation Test 2: non matching observations", { ) }) +## Test 3: empty slice ---- +test_that("slice_derivation Test 3: empty slice", { + advs <- tibble::tribble( + ~USUBJID, ~VSDTC, ~VSTPT, ~VSSEQ, + "1", "2020-04-16", NA_character_, 1, + "1", "2020-04-16", NA_character_, 2 + ) + + actual <- slice_derivation( + advs, + derivation = derive_vars_dtm, + args = params( + dtc = VSDTC, + new_vars_prefix = "A" + ), + derivation_slice( + filter = str_detect(VSTPT, "PRE|BEFORE"), + args = params(time_imputation = "first") + ), + derivation_slice( + filter = TRUE, + args = params(time_imputation = "last") + ) + ) + + expected <- mutate( + advs, + ADTM = c(ymd_hms("2020-04-16 23:59:59"), ymd_hms("2020-04-16 23:59:59")), + ATMF = "H" + ) + + expect_dfs_equal( + base = expected, + compare = actual, + keys = c("USUBJID", "VSSEQ") + ) +}) + # print.derivation_slice ---- -## print.derivation_slice Test 1: `derivation_slice` objects are printed as intended ---- +## Test 1: `derivation_slice` objects are printed as intended ---- test_that("print.derivation_slice Test1: `derivation_slice` objects are printed as intended", { slice <- derivation_slice(