diff --git a/.github/workflows/templates.yml b/.github/workflows/templates.yml index c693311d52..58d8cbc9f6 100644 --- a/.github/workflows/templates.yml +++ b/.github/workflows/templates.yml @@ -6,7 +6,7 @@ on: pull_request: branches: - main - - devel + - patch jobs: templates: diff --git a/NEWS.md b/NEWS.md index cdb5e9b036..712816b14a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,15 @@ were enhanced such that more than one summary variable can be derived, e.g., ## Various +- Website now has button/links to Slack channel and GitHub Issues (#2127) + +# admiral 0.12.3 + +- Fixed a bug in `derive_var_dthcaus()` where if a subject has observations in +more than one of the sources, the one from the last source was selected +regardless of the date. Now the function works as described in its +documentation. (#2154) + # admiral 0.12.2 - A unit test for `derive_param_computed()` was modified in anticipation of major user-facing changes to R version 4.4 (#2147) diff --git a/R/data.R b/R/data.R index d18679a327..6a167f70b4 100644 --- a/R/data.R +++ b/R/data.R @@ -88,7 +88,7 @@ #' Note: Variables `SOC`, `TERM`, `Grade 1`, `Grade 2`,`Grade 3`,`Grade 4`,`Grade 5`, `Definition` #' are from the source document on NCI-CTC website defining the grading criteria. #' [**Common Terminology Criteria for Adverse Events (CTCAE)v4.0**](https://ctep.cancer.gov/protocoldevelopment/electronic_applications/ctc.htm#ctc_40) -#' From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +#' From these variables only 'TERM' is used in the `{admiral}` code, the rest are for information and #' traceability only. #' #' @@ -124,7 +124,7 @@ #' Note: Variables `SOC`, `TERM`, `Grade 1`, `Grade 2`,`Grade 3`,`Grade 4`,`Grade 5`, `Definition` #' are from the source document on NCI-CTC website defining the grading criteria. #' [**Common Terminology Criteria for Adverse Events (CTCAE)v5.0**](https://ctep.cancer.gov/protocoldevelopment/electronic_applications/ctc.htm#ctc_50) -#' From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +#' From these variables only 'TERM' is used in the `{admiral}` code, the rest are for information and #' traceability only. #' #' @@ -162,7 +162,7 @@ #' Note: Variables `SOC`, `TERM`, `SUBGROUP`, `Grade 1`, `Grade 2`,`Grade 3`,`Grade 4`,`Grade 5`, `Definition` #' are from the source document on DAIDS website defining the grading criteria. #' [Division of AIDS (DAIDS) Table for Grading the Severity of Adult and Pediatric Adverse Events -#' From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +#' From these variables only 'TERM' is used in the `{admiral}` code, the rest are for information and #' traceability only. #' #' diff --git a/R/derive_date_vars.R b/R/derive_date_vars.R index 1c65d29c44..aa3a81f49c 100644 --- a/R/derive_date_vars.R +++ b/R/derive_date_vars.R @@ -101,7 +101,9 @@ #' `"23:59:59"`. Specifying date variables makes sense only if the date is #' imputed. If only time is imputed, date variables do not affect the result. -#' @param preserve Preserve day if month is missing and day is present +#' @param preserve Preserve lower level date/time part when higher order part +#' is missing, e.g. preserve day if month is missing or +#' preserve minute when hour is missing. #' #' For example `"2019---07"` would return `"2019-06-07` if `preserve = TRUE` #' (and `date_imputation = "mid"`). @@ -1248,7 +1250,7 @@ compute_tmf <- function(dtc, #' The date can be imputed (see `date_imputation` argument) #' and the date imputation flag ('`--DTF'`) can be added. #' -#' In {admiral} we don't allow users to pick any single part of the date/time to +#' In `{admiral}` we don't allow users to pick any single part of the date/time to #' impute, we only enable to impute up to a highest level, i.e. you couldn't #' choose to say impute months, but not days. #' @@ -1456,7 +1458,7 @@ derive_vars_dt <- function(dataset, # nolint: cyclocomp_linter #' The date and time can be imputed (see `date_imputation`/`time_imputation` arguments) #' and the date/time imputation flag (`'--DTF'`, `'--TMF'`) can be added. #' -#' In {admiral} we don't allow users to pick any single part of the date/time to +#' In `{admiral}` we don't allow users to pick any single part of the date/time to #' impute, we only enable to impute up to a highest level, i.e. you couldn't #' choose to say impute months, but not days. #' diff --git a/R/derive_var_dthcaus.R b/R/derive_var_dthcaus.R index f3f74631fb..e0e0bceca2 100644 --- a/R/derive_var_dthcaus.R +++ b/R/derive_var_dthcaus.R @@ -160,6 +160,8 @@ derive_var_dthcaus <- function(dataset, # process each source add_data <- vector("list", length(sources)) + tmp_source_nr <- get_new_tmp_var(dataset) + tmp_date <- get_new_tmp_var(dataset) for (ii in seq_along(sources)) { source_dataset_name <- sources[[ii]]$dataset_name source_dataset <- source_datasets[[source_dataset_name]] @@ -183,8 +185,6 @@ derive_var_dthcaus <- function(dataset, ) # if several death records, use the first/last according to 'mode' - tmp_source_nr <- get_new_tmp_var(dataset) - tmp_date <- get_new_tmp_var(dataset) add_data[[ii]] <- add_data[[ii]] %>% filter_extreme( order = exprs(!!date_var, !!!sources[[ii]]$order), diff --git a/R/derive_vars_dtm_to_tm.R b/R/derive_vars_dtm_to_tm.R index 8a4d64520b..b0fec71e9b 100644 --- a/R/derive_vars_dtm_to_tm.R +++ b/R/derive_vars_dtm_to_tm.R @@ -12,7 +12,7 @@ #' @details #' The names of the newly added variables are automatically set by replacing the #' `--DTM` suffix of the `source_vars` with `--TM`. The `--TM` variables are created -#' using the {hms} package. +#' using the `{hms}` package. #' #' @return #' A data frame containing the input dataset with the corresponding time diff --git a/R/duplicates.R b/R/duplicates.R index f4520d84fa..5a0ca78896 100644 --- a/R/duplicates.R +++ b/R/duplicates.R @@ -4,7 +4,7 @@ #' #' #' @details -#' Many {admiral} function check that the input dataset contains only one record +#' Many `{admiral}` function check that the input dataset contains only one record #' per `by_vars` group and throw an error otherwise. The `get_duplicates_dataset()` #' function allows one to retrieve the duplicate records that lead to an error. #' diff --git a/README.md b/README.md index b063a6f2c5..c5247888e4 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,17 @@ to develop ADaM datasets in R. ## Installation -The package is available from CRAN and can be installed by running `install.packages("admiral")`. - -To install the latest development version of the package directly from GitHub use the following code: +The package is available from CRAN and can be installed with ```r -if (!requireNamespace("remotes", quietly = TRUE)) { - install.packages("remotes") -} +install.packages("admiral") +``` -remotes::install_github("pharmaverse/pharmaversesdtm") # This is a required dependency of {admiral} -remotes::install_github("pharmaverse/admiraldev") # This is a required dependency of {admiral} -remotes::install_github("pharmaverse/admiral") +To install the development version of the package from GitHub run + +```r +# install.packages("devtools") +devtools::install_github("pharmaverse/admiral") ``` ## Release Schedule diff --git a/_pkgdown.yml b/_pkgdown.yml index bc8581f9fd..9d25486b16 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -145,6 +145,7 @@ reference: navbar: structure: left: [getstarted, reference, articles, community, news] + right: [search, slack, newissue, github] components: getstarted: text: Get Started @@ -199,5 +200,12 @@ navbar: href: articles/lab_grading.html - text: Hy's Law Implementation href: articles/hys_law.html - + slack: + icon: fa-slack + href: https://app.slack.com/client/T028PB489D3/C02M8KN8269 + aria-label: Slack + newissue: + icon: fa-bug + href: https://github.com/pharmaverse/admiral/issues/new/choose + aria-label: New Issue diff --git a/man/atoxgr_criteria_ctcv4.Rd b/man/atoxgr_criteria_ctcv4.Rd index 00e0a8ee32..c5bd444b31 100644 --- a/man/atoxgr_criteria_ctcv4.Rd +++ b/man/atoxgr_criteria_ctcv4.Rd @@ -41,7 +41,7 @@ value. 'L' is for LOW values, 'H' is for HIGH values. Note: the variable is case Note: Variables \code{SOC}, \code{TERM}, \verb{Grade 1}, \verb{Grade 2},\verb{Grade 3},\verb{Grade 4},\verb{Grade 5}, \code{Definition} are from the source document on NCI-CTC website defining the grading criteria. \href{https://ctep.cancer.gov/protocoldevelopment/electronic_applications/ctc.htm#ctc_40}{\strong{Common Terminology Criteria for Adverse Events (CTCAE)v4.0}} -From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +From these variables only 'TERM' is used in the \code{{admiral}} code, the rest are for information and traceability only. } \seealso{ diff --git a/man/atoxgr_criteria_ctcv5.Rd b/man/atoxgr_criteria_ctcv5.Rd index 70a3ef5aaa..31d09fa7ea 100644 --- a/man/atoxgr_criteria_ctcv5.Rd +++ b/man/atoxgr_criteria_ctcv5.Rd @@ -41,7 +41,7 @@ value. 'L' is for LOW values, 'H' is for HIGH values. Note: the variable is case Note: Variables \code{SOC}, \code{TERM}, \verb{Grade 1}, \verb{Grade 2},\verb{Grade 3},\verb{Grade 4},\verb{Grade 5}, \code{Definition} are from the source document on NCI-CTC website defining the grading criteria. \href{https://ctep.cancer.gov/protocoldevelopment/electronic_applications/ctc.htm#ctc_50}{\strong{Common Terminology Criteria for Adverse Events (CTCAE)v5.0}} -From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +From these variables only 'TERM' is used in the \code{{admiral}} code, the rest are for information and traceability only. } \seealso{ diff --git a/man/atoxgr_criteria_daids.Rd b/man/atoxgr_criteria_daids.Rd index c17e78adae..38bf96c953 100644 --- a/man/atoxgr_criteria_daids.Rd +++ b/man/atoxgr_criteria_daids.Rd @@ -43,7 +43,7 @@ value. 'L' is for LOW values, 'H' is for HIGH values. Note: the variable is case Note: Variables \code{SOC}, \code{TERM}, \code{SUBGROUP}, \verb{Grade 1}, \verb{Grade 2},\verb{Grade 3},\verb{Grade 4},\verb{Grade 5}, \code{Definition} are from the source document on DAIDS website defining the grading criteria. [Division of AIDS (DAIDS) Table for Grading the Severity of Adult and Pediatric Adverse Events -From these variables only 'TERM' is used in the {admiral} code, the rest are for information and +From these variables only 'TERM' is used in the \code{{admiral}} code, the rest are for information and traceability only. } \seealso{ diff --git a/man/convert_date_to_dtm.Rd b/man/convert_date_to_dtm.Rd index d15849dade..1fc0e944e1 100644 --- a/man/convert_date_to_dtm.Rd +++ b/man/convert_date_to_dtm.Rd @@ -113,7 +113,9 @@ For date variables (not datetime) in the list the time is imputed to \code{"23:59:59"}. Specifying date variables makes sense only if the date is imputed. If only time is imputed, date variables do not affect the result.} -\item{preserve}{Preserve day if month is missing and day is present +\item{preserve}{Preserve lower level date/time part when higher order part +is missing, e.g. preserve day if month is missing or +preserve minute when hour is missing. For example \code{"2019---07"} would return \verb{"2019-06-07} if \code{preserve = TRUE} (and \code{date_imputation = "mid"}). diff --git a/man/convert_dtc_to_dtm.Rd b/man/convert_dtc_to_dtm.Rd index 3d612f2092..3892f5e340 100644 --- a/man/convert_dtc_to_dtm.Rd +++ b/man/convert_dtc_to_dtm.Rd @@ -111,7 +111,9 @@ For date variables (not datetime) in the list the time is imputed to \code{"23:59:59"}. Specifying date variables makes sense only if the date is imputed. If only time is imputed, date variables do not affect the result.} -\item{preserve}{Preserve day if month is missing and day is present +\item{preserve}{Preserve lower level date/time part when higher order part +is missing, e.g. preserve day if month is missing or +preserve minute when hour is missing. For example \code{"2019---07"} would return \verb{"2019-06-07} if \code{preserve = TRUE} (and \code{date_imputation = "mid"}). diff --git a/man/derive_vars_dt.Rd b/man/derive_vars_dt.Rd index 1dbc3fb6b4..b79a07db63 100644 --- a/man/derive_vars_dt.Rd +++ b/man/derive_vars_dt.Rd @@ -132,7 +132,7 @@ The date can be imputed (see \code{date_imputation} argument) and the date imputation flag ('\verb{--DTF'}) can be added. } \details{ -In {admiral} we don't allow users to pick any single part of the date/time to +In \code{{admiral}} we don't allow users to pick any single part of the date/time to impute, we only enable to impute up to a highest level, i.e. you couldn't choose to say impute months, but not days. diff --git a/man/derive_vars_dtm.Rd b/man/derive_vars_dtm.Rd index f8bbd4f8c0..be218fac44 100644 --- a/man/derive_vars_dtm.Rd +++ b/man/derive_vars_dtm.Rd @@ -140,7 +140,9 @@ For date variables (not datetime) in the list the time is imputed to \code{"23:59:59"}. Specifying date variables makes sense only if the date is imputed. If only time is imputed, date variables do not affect the result.} -\item{preserve}{Preserve day if month is missing and day is present +\item{preserve}{Preserve lower level date/time part when higher order part +is missing, e.g. preserve day if month is missing or +preserve minute when hour is missing. For example \code{"2019---07"} would return \verb{"2019-06-07} if \code{preserve = TRUE} (and \code{date_imputation = "mid"}). @@ -168,7 +170,7 @@ The date and time can be imputed (see \code{date_imputation}/\code{time_imputati and the date/time imputation flag (\code{'--DTF'}, \code{'--TMF'}) can be added. } \details{ -In {admiral} we don't allow users to pick any single part of the date/time to +In \code{{admiral}} we don't allow users to pick any single part of the date/time to impute, we only enable to impute up to a highest level, i.e. you couldn't choose to say impute months, but not days. diff --git a/man/derive_vars_dtm_to_tm.Rd b/man/derive_vars_dtm_to_tm.Rd index 9d107f2f2c..8d4bbeaffc 100644 --- a/man/derive_vars_dtm_to_tm.Rd +++ b/man/derive_vars_dtm_to_tm.Rd @@ -25,7 +25,7 @@ This function creates time variable(s) as output from datetime variable(s) \details{ The names of the newly added variables are automatically set by replacing the \code{--DTM} suffix of the \code{source_vars} with \code{--TM}. The \code{--TM} variables are created -using the {hms} package. +using the \code{{hms}} package. } \examples{ library(tibble) diff --git a/man/get_duplicates_dataset.Rd b/man/get_duplicates_dataset.Rd index 59efe4fdcd..06ddf8112f 100644 --- a/man/get_duplicates_dataset.Rd +++ b/man/get_duplicates_dataset.Rd @@ -13,7 +13,7 @@ A \code{data.frame} or \code{NULL} Get Duplicate Records that Led to a Prior Error } \details{ -Many {admiral} function check that the input dataset contains only one record +Many \code{{admiral}} function check that the input dataset contains only one record per \code{by_vars} group and throw an error otherwise. The \code{get_duplicates_dataset()} function allows one to retrieve the duplicate records that lead to an error. diff --git a/man/impute_dtc_dtm.Rd b/man/impute_dtc_dtm.Rd index 8e0f8c0e8c..8abafde845 100644 --- a/man/impute_dtc_dtm.Rd +++ b/man/impute_dtc_dtm.Rd @@ -115,7 +115,9 @@ For date variables (not datetime) in the list the time is imputed to \code{"23:59:59"}. Specifying date variables makes sense only if the date is imputed. If only time is imputed, date variables do not affect the result.} -\item{preserve}{Preserve day if month is missing and day is present +\item{preserve}{Preserve lower level date/time part when higher order part +is missing, e.g. preserve day if month is missing or +preserve minute when hour is missing. For example \code{"2019---07"} would return \verb{"2019-06-07} if \code{preserve = TRUE} (and \code{date_imputation = "mid"}). diff --git a/tests/testthat/test-derive_var_dthcaus.R b/tests/testthat/test-derive_var_dthcaus.R index c9b6997a8d..5961512804 100644 --- a/tests/testthat/test-derive_var_dthcaus.R +++ b/tests/testthat/test-derive_var_dthcaus.R @@ -414,8 +414,8 @@ test_that("derive_var_dthcaus Test 8: `dataset` is sorted using the `order` para expect_dfs_equal(expected_output, actual_output, keys = "USUBJID") }) -## Test 9: returns a error when traceability_vars is used ---- -test_that("derive_var_dthcaus Test 9: returns a error when traceability_vars is used", { +## Test 9: returns a warning when traceability_vars is used ---- +test_that("derive_var_dthcaus Test 9: returns a warning when traceability_vars is used", { ae <- tibble::tribble( ~STUDYID, ~USUBJID, ~AESEQ, ~AEDECOD, ~AEOUT, ~AEDTHDTC, "TEST01", "PAT01", 12, "SUDDEN DEATH", "FATAL", "2021-04-04" @@ -437,3 +437,115 @@ test_that("derive_var_dthcaus Test 9: returns a error when traceability_vars is class = "lifecycle_error_deprecated" ) }) + +## Test 10: multiple observations from different sources ---- +test_that("derive_var_dthcaus Test 10: multiple observations from different sources", { + expected <- tibble::tribble( + ~STUDYID, ~USUBJID, ~DTHCAUS, + "TEST01", "PAT01", "SUDDEN DEATH", + "TEST01", "PAT02", NA_character_, + "TEST01", "PAT03", "DEATH DUE TO progression of disease" + ) + + adsl <- select(expected, -DTHCAUS) + + ae <- tibble::tribble( + ~STUDYID, ~USUBJID, ~AESEQ, ~AEDECOD, ~AEOUT, ~AEDTHDTC, + "TEST01", "PAT01", 12, "SUDDEN DEATH", "FATAL", "2021-04-04" + ) %>% + mutate( + AEDTHDT = ymd(AEDTHDTC) + ) + + ds <- tibble::tribble( + ~STUDYID, ~USUBJID, ~DSSEQ, ~DSDECOD, ~DSTERM, ~DSSTDTC, + "TEST01", "PAT01", 4, "DEATH", "DEATH DUE TO progression of disease", "2021-04-05", + "TEST01", "PAT02", 1, "INFORMED CONSENT OBTAINED", "INFORMED CONSENT OBTAINED", "2021-04-02", + "TEST01", "PAT02", 2, "RANDOMIZATION", "RANDOMIZATION", "2021-04-11", + "TEST01", "PAT02", 3, "COMPLETED", "PROTOCOL COMPLETED", "2021-12-01", + "TEST01", "PAT03", 1, "DEATH", "DEATH DUE TO progression of disease", "2021-04-07", + "TEST01", "PAT03", 2, "RANDOMIZATION", "RANDOMIZATION", "2021-04-11", + "TEST01", "PAT03", 3, "COMPLETED", "PROTOCOL COMPLETED", "2021-12-01" + ) + + # Derive `DTHCAUS` only - for on-study deaths only + src_ae <- dthcaus_source( + dataset_name = "ae", + filter = AEOUT == "FATAL", + date = convert_dtc_to_dt(AEDTHDTC), + mode = "first", + dthcaus = AEDECOD + ) + + src_ds <- dthcaus_source( + dataset_name = "ds", + filter = DSDECOD == "DEATH" & grepl("DEATH DUE TO", DSTERM), + date = convert_dtc_to_dt(DSSTDTC), + mode = "first", + dthcaus = DSTERM + ) + actual <- adsl %>% + derive_var_dthcaus(src_ae, src_ds, source_datasets = list(ae = ae, ds = ds)) + + expect_dfs_equal( + base = expected, + compare = actual, + keys = c("USUBJID") + ) +}) + +## Test 11: multiple observations from different sources with same date ---- +test_that("derive_var_dthcaus Test 11: multiple observations with same date", { + expected <- tibble::tribble( + ~STUDYID, ~USUBJID, ~DTHCAUS, + "TEST01", "PAT01", "SUDDEN DEATH", + "TEST01", "PAT02", NA_character_, + "TEST01", "PAT03", "DEATH DUE TO progression of disease" + ) + + adsl <- select(expected, -DTHCAUS) + + ae <- tibble::tribble( + ~STUDYID, ~USUBJID, ~AESEQ, ~AEDECOD, ~AEOUT, ~AEDTHDTC, + "TEST01", "PAT01", 12, "SUDDEN DEATH", "FATAL", "2021-04-05" + ) %>% + mutate( + AEDTHDT = ymd(AEDTHDTC) + ) + + ds <- tibble::tribble( + ~STUDYID, ~USUBJID, ~DSSEQ, ~DSDECOD, ~DSTERM, ~DSSTDTC, + "TEST01", "PAT01", 4, "DEATH", "DEATH DUE TO progression of disease", "2021-04-05", + "TEST01", "PAT02", 1, "INFORMED CONSENT OBTAINED", "INFORMED CONSENT OBTAINED", "2021-04-02", + "TEST01", "PAT02", 2, "RANDOMIZATION", "RANDOMIZATION", "2021-04-11", + "TEST01", "PAT02", 3, "COMPLETED", "PROTOCOL COMPLETED", "2021-12-01", + "TEST01", "PAT03", 1, "DEATH", "DEATH DUE TO progression of disease", "2021-04-07", + "TEST01", "PAT03", 2, "RANDOMIZATION", "RANDOMIZATION", "2021-04-11", + "TEST01", "PAT03", 3, "COMPLETED", "PROTOCOL COMPLETED", "2021-12-01" + ) + + # Derive `DTHCAUS` only - for on-study deaths only + src_ae <- dthcaus_source( + dataset_name = "ae", + filter = AEOUT == "FATAL", + date = convert_dtc_to_dt(AEDTHDTC), + mode = "first", + dthcaus = AEDECOD + ) + + src_ds <- dthcaus_source( + dataset_name = "ds", + filter = DSDECOD == "DEATH" & grepl("DEATH DUE TO", DSTERM), + date = convert_dtc_to_dt(DSSTDTC), + mode = "first", + dthcaus = DSTERM + ) + actual <- adsl %>% + derive_var_dthcaus(src_ae, src_ds, source_datasets = list(ae = ae, ds = ds)) + + expect_dfs_equal( + base = expected, + compare = actual, + keys = c("USUBJID") + ) +})