Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #2510 enhance derive param computed #2544

Merged
merged 6 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@

## Updates of Existing Functions

- The `keep_nas` argument of `derive_param_computed()` was enhanced such that it
manciniedoardo marked this conversation as resolved.
Show resolved Hide resolved
is now possible to specify a list of variables for which `NA`s are acceptable.
I.e., records are added even if some of the specified variables are `NA`.
(#2510)

## Breaking Changes

- The following function arguments are entering the next phase of the deprecation process: (#2487)
Expand Down
79 changes: 61 additions & 18 deletions R/derive_param_computed.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,18 @@
#' @param keep_nas Keep observations with `NA`s
#'
#' If the argument is set to `TRUE`, observations are added even if some of
#' the values contributing to the computed value are `NA`.
#' the values contributing to the computed value are `NA` (see Example 1b).
bms63 marked this conversation as resolved.
Show resolved Hide resolved
#'
#' If the argument is set to a list of variables, observations are added even
bms63 marked this conversation as resolved.
Show resolved Hide resolved
#' if some of specified variables are `NA` (see Example 1c).
#'
#' @details For each group (with respect to the variables specified for the
#' `by_vars` parameter) an observation is added to the output dataset if the
#' filtered input dataset (`dataset`) or the additional dataset
#' (`dataset_add`) contains exactly one observation for each parameter code
#' specified for `parameters`.
#' specified for `parameters` and all contributing values like `AVAL.SYSBP`
#' are not `NA`. The `keep_nas` can be used to specify variables for which
#' `NA`s are acceptable. See also Example 1b and 1c.
#'
#' For the new observations the variables specified for `set_values_to` are
#' set to the provided values. The values of the other variables of the input
Expand All @@ -145,17 +150,18 @@
#'
#' # Example 1a: Derive MAP
#' advs <- tribble(
#' ~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVALU, ~VISIT,
#' "01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 51, "mmHg", "BASELINE",
#' "01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 50, "mmHg", "WEEK 2",
#' "01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "mmHg", "BASELINE",
#' "01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "mmHg", "WEEK 2",
#' "01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 79, "mmHg", "BASELINE",
#' "01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 80, "mmHg", "WEEK 2",
#' "01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", 130, "mmHg", "BASELINE",
#' "01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", 132, "mmHg", "WEEK 2"
#' ~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~VISIT,
#' "01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 51, "BASELINE",
#' "01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 50, "WEEK 2",
#' "01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "BASELINE",
#' "01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "WEEK 2",
#' "01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 79, "BASELINE",
#' "01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 80, "WEEK 2",
#' "01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", 130, "BASELINE",
#' "01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", NA, "WEEK 2"
#' ) %>%
#' mutate(
#' AVALU = "mmHg",
#' ADT = case_when(
#' VISIT == "BASELINE" ~ as.Date("2024-01-10"),
#' VISIT == "WEEK 2" ~ as.Date("2024-01-24")
Expand All @@ -176,8 +182,8 @@
#' )
#' )
#'
#' # Example 1b: Using option `keep_nas = TRUE` to derive MAP in the case where some/all values
#' # of a variable used in the computation are missing
#' # Example 1b: Using option `keep_nas = TRUE` to derive MAP in the case where some/all
#' # values of a variable used in the computation are missing
#'
#' derive_param_computed(
#' advs,
Expand All @@ -194,6 +200,24 @@
#' keep_nas = TRUE
#' )
#'
#' # Example 1c: Using option `keep_nas = exprs(ADTF)` to derive MAP in the case where
#' # some/all values of a variable used in the computation are missing but ignoring ADTF
#'
#' derive_param_computed(
#' advs,
#' by_vars = exprs(USUBJID, VISIT),
#' parameters = c("SYSBP", "DIABP"),
#' set_values_to = exprs(
#' AVAL = (AVAL.SYSBP + 2 * AVAL.DIABP) / 3,
#' PARAMCD = "MAP",
#' PARAM = "Mean Arterial Pressure (mmHg)",
#' AVALU = "mmHg",
#' ADT = ADT.SYSBP,
#' ADTF = ADTF.SYSBP
yurovska marked this conversation as resolved.
Show resolved Hide resolved
#' ),
#' keep_nas = exprs(ADTF)
#' )
#'
#' # Example 2: Derive BMI where height is measured only once
#' advs <- tribble(
#' ~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVALU, ~VISIT,
Expand Down Expand Up @@ -303,7 +327,17 @@ derive_param_computed <- function(dataset = NULL,
if (!is.null(set_values_to$PARAMCD) && !is.null(dataset)) {
assert_param_does_not_exist(dataset, set_values_to$PARAMCD)
}
assert_logical_scalar(keep_nas)
if (typeof(keep_nas) == "list") {
assert_vars(keep_nas)
} else {
assert_logical_scalar(
keep_nas,
message = paste(
"Argument {.arg {arg_name}} must be either {.val {TRUE}}, {.val {FALSE}},",
"or a list of {.cls symbol}, but is {.obj_type_friendly {arg}}."
)
)
}

parameters <- assert_parameters_argument(parameters)
constant_parameters <- assert_parameters_argument(constant_parameters, optional = TRUE)
Expand Down Expand Up @@ -346,17 +380,26 @@ derive_param_computed <- function(dataset = NULL,
hori_data <- inner_join(hori_data, hori_const_data, by = vars2chr(constant_by_vars))
}

# add analysis value (AVAL) and parameter variables, e.g., PARAMCD
if (!keep_nas) {
# keep only observations where all analysis values are available
if (isFALSE(keep_nas) || typeof(keep_nas) == "list") {
# keep only observations where the specified analysis values are available
if (typeof(keep_nas) == "list") {
na_vars <- discard(
analysis_vars_chr,
~ str_detect(., paste0("^(", paste(vars2chr(keep_nas), collapse = "|"), ")\\."))
)
} else {
na_vars <- analysis_vars_chr
}
hori_data <- filter(
hori_data,
!!!parse_exprs(map_chr(
analysis_vars_chr,
na_vars,
~ str_c("!is.na(", .x, ")")
))
)
}

# add computed variables like AVAL and constant variables like PARAMCD
hori_data <- hori_data %>%
process_set_values_to(set_values_to) %>%
select(-all_of(analysis_vars_chr[str_detect(analysis_vars_chr, "\\.")]))
Expand Down
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
url: https://pharmaverse.github.io/admiral

template:
math-rendering: mathjax
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this intentional? Just checking!?! :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I rendered the documentation with pkgdown 2.1.1 and noticed that formulas are no longer rendered correctly. Adding this line fixes the issues.

bootstrap: 5
params:
bootswatch: flatly
Expand Down
50 changes: 37 additions & 13 deletions man/derive_param_computed.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions tests/testthat/_snaps/derive_param_computed.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# assert_parameters_argument Test 10: error if argument is of wrong type
# derive_param_computed Test 11: error if keep_nas is invalid

Code
derive_param_computed(advs, by_vars = exprs(USUBJID, AVISIT), parameters = c(
"SYSBP", "DIABP"), set_values_to = exprs(AVAL = (AVAL.SYSBP + 2 *
AVAL.DIABP) / 3, PARAMCD = "MAP", PARAM = "Mean Arterial Pressure (mmHg)"),
keep_nas = 3)
Condition
Error in `derive_param_computed()`:
! Argument `keep_nas` must be either TRUE, FALSE, or a list of <symbol>, but is a number.

# assert_parameters_argument Test 12: error if argument is of wrong type

Code
assert_parameters_argument(myparameters <- c(1, 2, 3))
Condition
Error in `assert_parameters_argument()`:
! `myparameters <- c(1, 2, 3)` must be a character vector or a list of expressions but it is a double vector.

# get_hori_data Test 11: error if variables with more than one dot
# get_hori_data Test 13: error if variables with more than one dot

Code
get_hori_data(input, parameters = exprs(SYSBP, DIABP), by_vars = exprs(USUBJID,
Expand Down
99 changes: 95 additions & 4 deletions tests/testthat/test-derive_param_computed.R
Original file line number Diff line number Diff line change
Expand Up @@ -399,18 +399,109 @@ test_that("derive_param_computed Test 9: compute multiple variables, keep_nas",
)
})

## Test 10: specify variables for keep_nas ----
test_that("derive_param_computed Test 10: specify variables for keep_nas", {
advs <- tibble::tribble(
~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVISIT,
"01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 51, "BASELINE",
"01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 50, "WEEK 2",
"01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "BASELINE",
"01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "WEEK 2",
"01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 79, "BASELINE",
"01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 80, "WEEK 2",
"01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", 130, "BASELINE",
"01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", NA, "WEEK 2"
) %>%
mutate(
ADT = case_when(
AVISIT == "BASELINE" ~ as.Date("2024-01-10"),
AVISIT == "WEEK 2" ~ as.Date("2024-01-24")
),
ADTF = NA_character_
)

expected <- bind_rows(
advs,
tibble::tribble(
~USUBJID, ~AVISIT, ~AVAL,
"01-701-1015", "BASELINE", (121 + 2 * 51) / 3,
"01-701-1015", "WEEK 2", (121 + 2 * 50) / 3,
"01-701-1028", "BASELINE", (130 + 2 * 79) / 3
) %>%
mutate(
PARAMCD = "MAP",
PARAM = "Mean Arterial Pressure (mmHg)",
ADT = case_when(
AVISIT == "BASELINE" ~ as.Date("2024-01-10"),
AVISIT == "WEEK 2" ~ as.Date("2024-01-24")
),
ADTF = NA_character_
)
)

actual <- derive_param_computed(
advs,
by_vars = exprs(USUBJID, AVISIT),
parameters = c("SYSBP", "DIABP"),
set_values_to = exprs(
AVAL = (AVAL.SYSBP + 2 * AVAL.DIABP) / 3,
PARAMCD = "MAP",
PARAM = "Mean Arterial Pressure (mmHg)",
ADT = ADT.SYSBP,
ADTF = ADTF.SYSBP
),
keep_nas = exprs(ADTF)
bms63 marked this conversation as resolved.
Show resolved Hide resolved
)

expect_dfs_equal(
base = expected,
compare = actual,
keys = c("USUBJID", "PARAMCD", "AVISIT")
)
})

## Test 11: error if keep_nas is invalid ----
test_that("derive_param_computed Test 11: error if keep_nas is invalid", {
advs <- tibble::tribble(
~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVISIT,
"01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 51, "BASELINE",
"01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 50, "WEEK 2",
"01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "BASELINE",
"01-701-1015", "SYSBP", "Systolic Blood Pressure (mmHg)", 121, "WEEK 2",
"01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 79, "BASELINE",
"01-701-1028", "DIABP", "Diastolic Blood Pressure (mmHg)", 80, "WEEK 2",
"01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", 130, "BASELINE",
"01-701-1028", "SYSBP", "Systolic Blood Pressure (mmHg)", NA, "WEEK 2"
)

expect_snapshot(
derive_param_computed(
advs,
by_vars = exprs(USUBJID, AVISIT),
parameters = c("SYSBP", "DIABP"),
set_values_to = exprs(
AVAL = (AVAL.SYSBP + 2 * AVAL.DIABP) / 3,
PARAMCD = "MAP",
PARAM = "Mean Arterial Pressure (mmHg)"
),
keep_nas = 3
),
error = TRUE
)
})

# assert_parameters_argument ----
## Test 10: error if argument is of wrong type ----
test_that("assert_parameters_argument Test 10: error if argument is of wrong type", {
## Test 12: error if argument is of wrong type ----
test_that("assert_parameters_argument Test 12: error if argument is of wrong type", {
expect_snapshot(
assert_parameters_argument(myparameters <- c(1, 2, 3)),
error = TRUE
)
})

# get_hori_data ----
## Test 11: error if variables with more than one dot ----
test_that("get_hori_data Test 11: error if variables with more than one dot", {
## Test 13: error if variables with more than one dot ----
test_that("get_hori_data Test 13: error if variables with more than one dot", {
input <- tibble::tribble(
~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVALU, ~VISIT,
"01-701-1015", "DIABP", "Diastolic Blood Pressure (mmHg)", 51, "mmHg", "BASELINE",
Expand Down
Loading