diff --git a/NEWS.md b/NEWS.md index d25a87e2..83a3b750 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,12 +1,30 @@ # admiralvaccine 0.3.0 +## Updates related to CBER requirements for eDiary data + +- Updated ADFACE template and vignette as per new SDTM mapping of Investigator assessment for eDiary data, as recommended by CBER. The collection of the Investigator assessment can happen when data reported by the participants was deemed incorrect or the participant did not complete the eDiary. In these two scenarios, the Investigator assessment is collected within the eDiary platform as a separate record from the original data reported by the participant (if this is allowed by eCOA system) or in the study eCRF. This leads to a change in Solicited Adverse Event SDTM structure (FACE and VS). Additional records coming from Investigator assessment are added, which can be identified through an evaluator variable (FAEVAL/VSEVAL). An update in ADFACE has been provided in order to reflect these changes in SDTM. (#243) + ## Breaking Changes -- Removed `dataset_supp` and `dataset_suppex` arguments from `derive_vars_merged_vaccine()` as we are not combining the parental with supplementary inside the function, but can be optionally combined in the ADCE, ADFACE and ADIS templates using `combine_supp()` function from {metatools}. (#246) +- Removed `dataset_supp` and `dataset_suppex` arguments from `derive_vars_merged_vaccine()` as we are not combining parental with supplementary domains inside the function, but can be optionally combined in the ADCE, ADFACE and ADIS templates using `combine_supp()` function from {metatools}. (#246) + +- Included an argument `filter_add` in `derive_diam_to_sev_records()` to pass the subset condition to consider the particular diameter record for convert them to severity records. ## Updates to Templates -- Supplementary domains are now optionally combined with parental domain within the template. (#246) +- Included a step to derive ANL01FL in ADFACE template, to flag the records which would be considered for analysis purpose. + +- Supplementary domains are now optionally combined with parental domains in ADFACE and ADIS templates. (#246) + +## Updates to Documentation + +- Included a step to derive ANL01FL in ADFACE vignette, to flag the records which would be considered for analysis purpose. + +- Supplementary domains are now optionally combined with parental domains n ADFACE and ADIS vignettes. (#246) + +## Various + +- {metatools} and {styler} were added to 'Suggests'. (#246, #239) # admiralvaccine 0.2.0 diff --git a/R/derive_diam_to_sev_records.R b/R/derive_diam_to_sev_records.R index c5a3ca3e..acf893c6 100644 --- a/R/derive_diam_to_sev_records.R +++ b/R/derive_diam_to_sev_records.R @@ -7,7 +7,7 @@ #' #' The variables `USUBJID`,`FAOBJ`,`AVAL`, `AVALC`, `FATESTCD` and `FATEST` are expected #' for Input data set. -#' +#' @param filter_add filter for the `dataset`. #' @param diam_code Diameter record filter #' #' *Permitted Value*: A character vector or scalar. @@ -121,6 +121,7 @@ #' @family der_rec #' derive_diam_to_sev_records <- function(dataset, + filter_add = NULL, diam_code = "DIAMETER", faobj_values = c("REDNESS", "SWELLING"), testcd_sev = "SEV", @@ -140,6 +141,8 @@ derive_diam_to_sev_records <- function(dataset, optional = FALSE ) + filter_add <- assert_filter_cond(enexpr(filter_add), optional = TRUE) + # Checking & Removing the records which has severity records for the FAOBJ diam <- dataset %>% filter(FAOBJ %in% faobj_values) @@ -151,6 +154,10 @@ derive_diam_to_sev_records <- function(dataset, # Replacing FATESTCD and FATEST for Diameter with Severity ds <- function(diam_code) { if (c(diam_code) %in% diam$FATESTCD) { + if (!is.null(filter_add)) { + fil_rec <- fil_rec %>% + filter(!!filter_add) + } sev <- fil_rec %>% filter(FAOBJ %in% faobj_values & FATESTCD %in% diam_code) %>% mutate( diff --git a/inst/WORDLIST b/inst/WORDLIST index bbcf553b..245b5198 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -67,3 +67,10 @@ reactogenicity ungrouped xportr xpt +eCRF +eCOA +eDiary +FAEVAL +VSEVAL +ANL +styler diff --git a/inst/templates/ad_adface.R b/inst/templates/ad_adface.R index 844cbef0..c513976c 100644 --- a/inst/templates/ad_adface.R +++ b/inst/templates/ad_adface.R @@ -121,40 +121,50 @@ adface <- derive_vars_joined( ATPT = FATPT, ATPTN = FATPTNUM ) %>% - # Step 8 - Creating severity records from Diameter for Redness, Swelling,etc - # Note: Basically, this function will derive and create the severity records from the - # diameter record for the particular events that user wants. If you want to derive the Severity - # from diameter, even though you have the severity in SDTM level, this function will re-derive the - # severity and remove the derived SDTM severity records. - derive_diam_to_sev_records( - diam_code = "DIAMETER", - faobj_values = c("REDNESS", "SWELLING"), - testcd_sev = "SEV", - test_sev = "Severity/Intensity", - none = 0, - mild = 2, - mod = 5, - sev = 10 + # Please, consider which assessment is needed for your analysis. If you want to prioritize + # Instigator assessment, please proceed as follows. Otherwise, change FAEVAL order. + derive_var_extreme_flag( + by = exprs(STUDYID, USUBJID, FATPTREF, FAOBJ, FATESTCD, FATPTNUM), + order = exprs(STUDYID, USUBJID, FATPTREF, FAOBJ, FATESTCD, FATPTNUM, FAEVAL), + new_var = ANL01FL, + mode = "first", + true_value = "Y", + false_value = NA_character_ ) + +# Version 0.3.0: as per CBER requirement, Investigator assessment has been added into FACE, +# which is identified by "INVESTIGATOR" value, in FAEVAL. + +# step 8 - Derive the severity records from the Diameter records for the redness and swelling. +adface <- adface %>% derive_diam_to_sev_records( + filter_add = ANL01FL == "Y", + diam_code = "DIAMETER", + faobj_values = c("REDNESS", "SWELLING"), + testcd_sev = "SEV", + test_sev = "Severity/Intensity", + none = 0, + mild = 2, + mod = 5, + sev = 10 +) + # Step 9 - Deriving Maximum Severity for Local and Systemic events -adface <- adface %>% - derive_extreme_records( - dataset_add = adface, - filter = FATESTCD == "SEV", - by_vars = exprs(USUBJID, FAOBJ, ATPTREF), - order = exprs(AVAL), - check_type = "none", - mode = "last", - set_values_to = exprs( - FATEST = "Maximum Severity", - FATESTCD = "MAXSEV" - ) +adface <- adface %>% derive_extreme_records( + dataset_add = adface, + filter = FATESTCD == "SEV" & ANL01FL == "Y", + by_vars = exprs(USUBJID, FAOBJ, ATPTREF), + order = exprs(AVAL), + check_type = "none", + mode = "last", + set_values_to = exprs( + FATEST = "Maximum Severity", + FATESTCD = "MAXSEV" ) -# Step 10 - Deriving Maximum Diameter for Administrative Site Reactions -adface <- adface %>% +) %>% + # Step 10 - Deriving Maximum Diameter for Administrative Site Reactions derive_extreme_records( dataset_add = adface, - filter = FAOBJ %in% c("REDNESS", "SWELLING") & FATESTCD == "DIAMETER", + filter = FAOBJ %in% c("REDNESS", "SWELLING") & FATESTCD == "DIAMETER" & ANL01FL == "Y", by_vars = exprs(USUBJID, FAOBJ, FALNKGRP), order = exprs(AVAL), check_type = "none", @@ -167,7 +177,7 @@ adface <- adface %>% # Step 11 - Deriving Maximum Temperature derive_extreme_records( dataset_add = adface, - filter = FAOBJ == "FEVER", + filter = FAOBJ == "FEVER" & ANL01FL == "Y", by_vars = exprs(USUBJID, FAOBJ, ATPTREF), order = exprs(VSSTRESN), check_type = "none", @@ -222,8 +232,8 @@ adface <- derive_vars_params( ) %>% # Step 13 - Maximum flag ANL01FL and ANL02FL derive_vars_max_flag( - flag1 = "ANL01FL", - flag2 = "ANL02FL" + flag1 = "ANL02FL", + flag2 = "ANL03FL" ) %>% # Step 14 - Creating flag variables for occurred events derive_vars_event_flag( diff --git a/man/derive_diam_to_sev_records.Rd b/man/derive_diam_to_sev_records.Rd index 6890bf3a..6bc00127 100644 --- a/man/derive_diam_to_sev_records.Rd +++ b/man/derive_diam_to_sev_records.Rd @@ -6,6 +6,7 @@ \usage{ derive_diam_to_sev_records( dataset, + filter_add = NULL, diam_code = "DIAMETER", faobj_values = c("REDNESS", "SWELLING"), testcd_sev = "SEV", @@ -22,6 +23,8 @@ derive_diam_to_sev_records( The variables \code{USUBJID},\code{FAOBJ},\code{AVAL}, \code{AVALC}, \code{FATESTCD} and \code{FATEST} are expected for Input data set.} +\item{filter_add}{filter for the \code{dataset}.} + \item{diam_code}{Diameter record filter \emph{Permitted Value}: A character vector or scalar. diff --git a/tests/testthat/test-derive_diam_to_sev_records.R b/tests/testthat/test-derive_diam_to_sev_records.R index 1dfec63b..838712cc 100644 --- a/tests/testthat/test-derive_diam_to_sev_records.R +++ b/tests/testthat/test-derive_diam_to_sev_records.R @@ -180,15 +180,16 @@ test_that("derive_diam_to_sev_records Test 3: Check if the arguments `none`, test_that("derive_diam_to_sev_records Test 4: Check if the input dataset has severity records and remove those records correctly", { input <- tibble::tribble( - ~USUBJID, ~FAOBJ, ~AVAL, ~AVALC, ~ATPTREF, ~FATEST, ~FATESTCD, - "XYZ1001", "REDNESS", 1.5, "1.5", "VACCINATION 1", "Diameter", "DIAMETER", - "XYZ1001", "REDNESS", 11, "11", "VACCINATION 1", "Diameter", "DIAMETER", - "XYZ1001", "SWELLING", 6.5, "7.5", "VACCINATION 1", "Diameter", "DIAMETER", - "XYZ1001", "SWELLING", 4.5, "3.5", "VACCINATION 1", "Diameter", "DIAMETER", - "XYZ1001", "REDNESS", 1.5, "NONE", "VACCINATION 1", "Severity", "SEV", - "XYZ1001", "REDNESS", 11, "SEVERE", "VACCINATION 1", "Severity", "SEV", - "XYZ1001", "SWELLING", 6.5, "MODERATE", "VACCINATION 1", "Severity", "SEV", - "XYZ1001", "SWELLING", 4.5, "MILD", "VACCINATION 1", "Severity", "SEV" + ~USUBJID, ~FAOBJ, ~AVAL, ~AVALC, ~ATPTREF, ~FATEST, ~FATESTCD, ~FAEVAL, ~ANL01FL, + "XYZ1001", "REDNESS", 1.5, "1.5", "VACCINATION 1", "Diameter", "DIAMETER", "SUBJECT", "Y", + "XYZ1001", "REDNESS", 11, "11", "VACCINATION 1", "Diameter", "DIAMETER", "SUBJECT", "Y", + "XYZ1001", "SWELLING", 6.5, "7.5", "VACCINATION 1", "Diameter", "DIAMETER", "SUBJECT", "Y", + "XYZ1001", "SWELLING", 4.5, "3.5", "VACCINATION 1", "Diameter", "DIAMETER", "SUBJECT", "Y", + "XYZ1001", "REDNESS", 1.5, "NONE", "VACCINATION 1", "Severity", "SEV", "SUBJECT", "N", + "XYZ1001", "REDNESS", 1.5, "NONE", "VACCINATION 1", "Severity", "SEV", "INVESTIGATOR", "Y", + "XYZ1001", "REDNESS", 11, "SEVERE", "VACCINATION 1", "Severity", "SEV", "SUBJECT", "Y", + "XYZ1001", "SWELLING", 6.5, "MODERATE", "VACCINATION 1", "Severity", "SEV", "SUBJECT", "Y", + "XYZ1001", "SWELLING", 4.5, "MILD", "VACCINATION 1", "Severity", "SEV", "SUBJECT", "Y", ) format_avalc <- function(x) { @@ -201,7 +202,7 @@ test_that("derive_diam_to_sev_records Test 4: Check if the input dataset has } input <- input %>% - filter(FATESTCD != "SEV" & FAOBJ %in% c("REDNESS", "SWELLING")) + filter(ANL01FL == "Y" & FATESTCD != "SEV" & FAOBJ %in% c("REDNESS", "SWELLING")) expected1 <- input %>% mutate( @@ -224,6 +225,7 @@ test_that("derive_diam_to_sev_records Test 4: Check if the input dataset has actual_output <- derive_diam_to_sev_records( dataset = input, + filter_add = ANL01FL == "Y", diam_code = "DIAMETER", faobj_values = c("REDNESS", "SWELLING"), testcd_sev = "SEV", diff --git a/vignettes/adface.Rmd b/vignettes/adface.Rmd index b6ac9345..cfe8352a 100644 --- a/vignettes/adface.Rmd +++ b/vignettes/adface.Rmd @@ -258,7 +258,8 @@ dataset_vignette( ## Derive Direct Mapping Variables {#mapping} -In this step,we will create the user defined function to assign `AVAL` values from `AVALC` which will be used in further steps. +In this step,we will create the user defined function to assign `AVAL` values from `AVALC` which +will be used in further steps. The user defined functions would look like the following: @@ -295,6 +296,29 @@ dataset_vignette( display_vars = exprs(USUBJID, FAOBJ, AVAL, AVALC, ATPTREF, ATPTN) ) ``` +## Derive AN01FL +Creating ANL01FL which would flag the records that will be considered for analysis and if there is any Investigator and Subject record for the same day, it would flag the Investigator record over the subject record. + +Note: Please, consider which assessment is needed for your analysis. If you want to prioritize Investigator assessment, please proceed as follows. Otherwise, change FAEVAL order. + +```{r eval = TRUE} +adface <- adface %>% derive_var_extreme_flag( + by = exprs(STUDYID, USUBJID, FATPTREF, FAOBJ, FATESTCD, FATPTNUM), + order = exprs(STUDYID, USUBJID, FATPTREF, FAOBJ, FATESTCD, FATPTNUM, FAEVAL), + new_var = ANL01FL, + mode = "first", + true_value = "Y", + false_value = NA_character_ +) +``` + +```{r, echo=FALSE} +dataset_vignette( + adface, + display_vars = exprs(USUBJID, FAOBJ, ATPTREF, FATESTCD, FATEST, AVAL, ANL01FL), + filter = ANL01FL == "Y" +) +``` ## Derive Severity Records for Administration Site Events {#sev} @@ -305,6 +329,7 @@ The severity records created will be useful for calculating the maximum severity ```{r eval=TRUE} adface <- derive_diam_to_sev_records( dataset = adface, + filter_add = ANL01FL == "Y", diam_code = "DIAMETER", faobj_values = c("REDNESS", "SWELLING"), testcd_sev = "SEV", @@ -336,7 +361,7 @@ In this step, we will derive maximum records for severity, diameter, temperature adface <- derive_extreme_records( dataset = adface, dataset_add = adface, - filter_add = FATESTCD == "SEV", + filter_add = FATESTCD == "SEV" & ANL01FL == "Y", by_vars = exprs(USUBJID, FAOBJ, ATPTREF), order = exprs(AVAL), check_type = "none", @@ -350,7 +375,7 @@ adface <- derive_extreme_records( adface <- derive_extreme_records( dataset = adface, dataset_add = adface, - filter_add = FAOBJ %in% c("REDNESS", "SWELLING") & FATESTCD == "DIAMETER", + filter_add = FAOBJ %in% c("REDNESS", "SWELLING") & FATESTCD == "DIAMETER" & ANL01FL == "Y", by_vars = exprs(USUBJID, FAOBJ, FALNKGRP), order = exprs(AVAL), check_type = "none", @@ -364,7 +389,7 @@ adface <- derive_extreme_records( adface <- derive_extreme_records( dataset = adface, dataset_add = adface, - filter_add = FAOBJ == "FEVER", + filter_add = FAOBJ == "FEVER" & ANL01FL == "Y", by_vars = exprs(USUBJID, FAOBJ, ATPTREF), order = exprs(VSSTRESN), check_type = "none", @@ -476,8 +501,8 @@ The function `derive_vars_max_flag()` is used to derive flag variable for the ma ```{r eval=TRUE} adface <- derive_vars_max_flag( dataset = adface, - flag1 = "ANL01FL", - flag2 = "ANL02FL" + flag1 = "ANL02FL", + flag2 = "ANL03FL" ) ``` @@ -488,7 +513,7 @@ dataset_vignette( ) ``` -This call would return the input dataset with columns `ANL01FL`, `ANL02FL` added by default. +This call would return the input dataset with columns `ANL02FL`, `ANL03FL` added by default. This function allows the user to change the name of the new variables created. ## Derive Event Occurrence Flag {#eventflag}