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 #2481 bug the result of derive param tte depends on the sort order of the input #2569

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8e23388
Added order arguments to censor_source and event_source. Also added s…
ProfessorP-beep Nov 18, 2024
cd52801
Added order argument to tte_source as part of development and error f…
ProfessorP-beep Nov 18, 2024
2727736
Fixed previous erros but still need to address failed tests for Test …
ProfessorP-beep Nov 18, 2024
9e86217
added check_type arg_match to derive_param_tte so user has to input a…
ProfessorP-beep Nov 18, 2024
d97377c
Changed position of signal_duplicate_records function in derive_param…
ProfessorP-beep Nov 18, 2024
fa49a51
lintr changes by removing whitespace.
ProfessorP-beep Nov 18, 2024
01e8f5a
styler fix.
ProfessorP-beep Nov 18, 2024
53457c2
updated NEWS.md with changes to derive_param_tte,. Removed Test 17 fr…
ProfessorP-beep Nov 19, 2024
020c9d7
Merge branch 'main' into 2481-bug-the-result-of-derive_param_tte-depe…
ProfessorP-beep Nov 19, 2024
dccdbe1
changed the signal_duplicate_records within derive_parame_tte to hand…
ProfessorP-beep Nov 19, 2024
8006891
Merge branch '2481-bug-the-result-of-derive_param_tte-depends-on-the-…
ProfessorP-beep Nov 19, 2024
4c95243
added a tryCatch() to filter_date_sources to catch duplicates to addr…
ProfessorP-beep Nov 21, 2024
087c0f3
Moved duplication check to filter_date_sources in tryCatch() and rewr…
ProfessorP-beep Nov 24, 2024
4405868
1. Moved updates in News section to admiral dev section
ProfessorP-beep Dec 3, 2024
21b5a00
Ran styler, lintr fixes, and devtools check.
ProfessorP-beep Dec 3, 2024
ce07ad1
styler changes
ProfessorP-beep Dec 3, 2024
1d4e6b7
accepted snapshots from testthat and addressed bds_tte.Rmd error for …
ProfessorP-beep Dec 3, 2024
22f3f2d
added documentation for order and check_type arguments added to funct…
ProfessorP-beep Dec 3, 2024
47637a5
requested updates to documentation and test script for derive_param_tte
ProfessorP-beep Dec 16, 2024
e882758
corrected documentation and removed rlang from bds_tte.Rmd
ProfessorP-beep Dec 17, 2024
e5c28fc
updated derive_param_tte documentation and added test to derive_param…
ProfessorP-beep Dec 20, 2024
404c949
fixed spelling error
ProfessorP-beep Dec 20, 2024
ae70492
updates to derive_param_tte documentation and test examples.
ProfessorP-beep Dec 23, 2024
34d2fb3
Update NEWS.md
ProfessorP-beep Jan 8, 2025
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
38 changes: 31 additions & 7 deletions R/derive_param_tte.R
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,10 @@ derive_param_tte <- function(dataset = NULL,
censor_conditions,
create_datetime = FALSE,
set_values_to,
subject_keys = get_admiral_option("subject_keys")) {
subject_keys = get_admiral_option("subject_keys"),
check_type = "warning") {
# Match check_type to valid admiral options
check_type <- rlang::arg_match(check_type, c("warning", "message", "error", "none"))
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved
# checking and quoting #
assert_data_frame(dataset, optional = TRUE)
assert_vars(by_vars, optional = TRUE)
Expand Down Expand Up @@ -375,6 +378,7 @@ derive_param_tte <- function(dataset = NULL,
}

tmp_event <- get_new_tmp_var(dataset)

# determine events #
event_data <- filter_date_sources(
sources = event_conditions,
Expand All @@ -386,6 +390,13 @@ derive_param_tte <- function(dataset = NULL,
) %>%
mutate(!!tmp_event := 1L)

# check for duplicates in event_data
signal_duplicate_records(
dataset = event_data,
by_vars = expr_c(by_vars, subject_keys),
cnd_type = check_type
)
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved

# determine censoring observations #
censor_data <- filter_date_sources(
sources = censor_conditions,
Expand All @@ -397,6 +408,13 @@ derive_param_tte <- function(dataset = NULL,
) %>%
mutate(!!tmp_event := 0L)

# check for duplicates in censor_data
signal_duplicate_records(
dataset = censor_data,
by_vars = expr_c(by_vars, subject_keys),
cnd_type = check_type
)

# determine variable to add from ADSL #
if (create_datetime) {
date_var <- sym("ADTM")
Expand Down Expand Up @@ -793,7 +811,8 @@ tte_source <- function(dataset_name,
filter = NULL,
date,
censor = 0,
set_values_to = NULL) {
set_values_to = NULL,
order = order) {
out <- list(
dataset_name = assert_character_scalar(dataset_name),
filter = assert_filter_cond(enexpr(filter), optional = TRUE),
Expand All @@ -803,7 +822,8 @@ tte_source <- function(dataset_name,
set_values_to,
named = TRUE,
optional = TRUE
)
),
order = order
)
class(out) <- c("tte_source", "source", "list")
out
Expand Down Expand Up @@ -844,13 +864,15 @@ tte_source <- function(dataset_name,
event_source <- function(dataset_name,
filter = NULL,
date,
set_values_to = NULL) {
set_values_to = NULL,
order = NULL) {
out <- tte_source(
dataset_name = assert_character_scalar(dataset_name),
filter = !!enexpr(filter),
date = !!assert_expr(enexpr(date)),
censor = 0,
set_values_to = set_values_to
set_values_to = set_values_to,
order = order
)
class(out) <- c("event_source", class(out))
out
Expand Down Expand Up @@ -891,13 +913,15 @@ censor_source <- function(dataset_name,
filter = NULL,
date,
censor = 1,
set_values_to = NULL) {
set_values_to = NULL,
order = NULL) {
out <- tte_source(
dataset_name = assert_character_scalar(dataset_name),
filter = !!enexpr(filter),
date = !!assert_expr(enexpr(date)),
censor = assert_integer_scalar(censor, subset = "positive"),
set_values_to = set_values_to
set_values_to = set_values_to,
order = order
)
class(out) <- c("censor_source", class(out))
out
Expand Down
3 changes: 2 additions & 1 deletion man/censor_source.Rd

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

3 changes: 2 additions & 1 deletion man/derive_param_tte.Rd

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

8 changes: 7 additions & 1 deletion man/event_source.Rd

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

9 changes: 8 additions & 1 deletion man/tte_source.Rd

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

15 changes: 0 additions & 15 deletions tests/testthat/_snaps/derive_param_tte.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,6 @@
! For some values of "PARAMCD" there is more than one value of "AEDECOD"
i Call `admiral::get_one_to_many_dataset()` to get all one-to-many values.

# derive_param_tte Test 9: errors if set_values_to contains invalid expressions

Code
derive_param_tte(dataset_adsl = adsl, by_vars = exprs(AEDECOD), start_date = TRTSDT,
event_conditions = list(ttae), censor_conditions = list(eos), source_datasets = list(
adsl = adsl, ae = ae), set_values_to = exprs(PARAMCD = paste0("TTAE",
as.numeric(as.factor(AEDECOD))), PARAM = past("Time to First", AEDECOD,
"Adverse Event"), PARCAT1 = "TTAE", PARCAT2 = AEDECOD))
Condition
Error in `process_set_values_to()`:
! Assigning variables failed!
* `set_values_to = exprs(PARAMCD = paste0("TTAE", as.numeric(as.factor(AEDECOD))), PARAM = past("Time to First", AEDECOD, "Adverse Event"), PARCAT1 = TTAE, PARCAT2 = AEDECOD)`
See error message below:
i In argument: `PARAM = past("Time to First", AEDECOD, "Adverse Event")`. Caused by error in `past()`: ! could not find function "past"

# list_tte_source_objects Test 13: error is issued if package does not exist

Code
Expand Down
207 changes: 206 additions & 1 deletion tests/testthat/test-derive_param_tte.R
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ test_that("derive_param_tte Test 9: errors if set_values_to contains invalid exp
source_datasets = list(adsl = adsl, ae = ae),
set_values_to = exprs(
PARAMCD = paste0("TTAE", as.numeric(as.factor(AEDECOD))),
PARAM = past("Time to First", AEDECOD, "Adverse Event"),
PARAM = paste("Time to First", AEDECOD, "Adverse Event"),
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved
PARCAT1 = "TTAE",
PARCAT2 = AEDECOD
)
Expand Down Expand Up @@ -928,3 +928,208 @@ test_that("list_tte_source_objects Test 14: expected objects produced", {

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 when check_type = 'warning'", {
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved
# Define ADSL dataset
adsl <- tibble::tribble(
~USUBJID, ~TRTSDT, ~TRTEDT, ~EOSDT,
"01", ymd("2020-12-06"), ymd("2021-03-02"), ymd("2021-03-06"),
"02", ymd("2021-01-16"), ymd("2021-01-20"), ymd("2021-02-03")
) %>%
mutate(STUDYID = "AB42")

# Define AE dataset with duplicates
ae <- tibble::tribble(
~USUBJID, ~AESTDTC, ~AESEQ, ~AEDECOD,
"01", "2021-01-03", 1, "Flu",
"01", "2021-03-04", 2, "Cough",
"01", "2021-01-03", 3, "Flu"
) %>%
mutate(
STUDYID = "AB42",
AESTDT = ymd(AESTDTC)
)

# Define event source
ttae <- event_source(
dataset_name = "ae",
date = AESTDT,
set_values_to = exprs(
EVENTDESC = "AE",
SRCDOM = "AE",
SRCVAR = "AESTDTC",
SRCSEQ = AESEQ
)
)

# Define censor source
eot <- censor_source(
dataset_name = "adsl",
date = pmin(TRTEDT + days(10), EOSDT),
censor = 1,
set_values_to = exprs(
EVENTDESC = "END OF TRT",
SRCDOM = "ADSL",
SRCVAR = "TRTEDT"
)
)

# Test for duplicate detection
expect_warning(
Copy link
Collaborator

Choose a reason for hiding this comment

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

expect_snapshot() should be used because the message is created by the function which is tested. This ensures that the complete message looks as intended.

derive_param_tte(
dataset_adsl = adsl,
start_date = TRTSDT,
event_conditions = list(ttae),
censor_conditions = list(eot),
source_datasets = list(adsl = adsl, ae = ae),
set_values_to = exprs(PARAMCD = "TTAE"),
check_type = "warning"
),
regexp = "Dataset contains duplicate records"
)
})

# 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", {
# Define ADSL dataset
adsl <- tibble::tribble(
~USUBJID, ~TRTSDT, ~TRTEDT, ~EOSDT,
"01", ymd("2020-12-06"), ymd("2021-03-02"), ymd("2021-03-06"),
"02", ymd("2021-01-16"), ymd("2021-01-20"), ymd("2021-02-03")
) %>%
mutate(STUDYID = "AB42")

# Define AE dataset
ae <- tibble::tribble(
~USUBJID, ~AESTDTC, ~AESEQ, ~AEDECOD,
"01", "2021-01-03", 1, "Flu",
"01", "2021-03-04", 2, "Cough",
"01", "2021-01-03", 3, "Flu"
) %>%
mutate(
STUDYID = "AB42",
AESTDT = ymd(AESTDTC)
)

# Define event source with order
ttae <- event_source(
dataset_name = "ae",
date = AESTDT,
set_values_to = exprs(
EVENTDESC = "AE",
SRCDOM = "AE",
SRCVAR = "AESTDTC",
SRCSEQ = AESEQ
),
order = exprs(AESEQ)
)

# Define censor source with order
eot <- censor_source(
dataset_name = "adsl",
date = pmin(TRTEDT + days(10), EOSDT),
censor = 1,
set_values_to = exprs(
EVENTDESC = "END OF TRT",
SRCDOM = "ADSL",
SRCVAR = "TRTEDT"
),
order = exprs(TRTEDT)
)

# Run derive_param_tte with sorted AE dataset
result_sorted <- derive_param_tte(
dataset_adsl = adsl,
start_date = TRTSDT,
event_conditions = list(ttae),
censor_conditions = list(eot),
source_datasets = list(adsl = adsl, ae = arrange(ae, AESEQ)),
set_values_to = exprs(PARAMCD = "TTAE")
)

# Run derive_param_tte with reverse-sorted AE dataset
result_unsorted <- derive_param_tte(
dataset_adsl = adsl,
start_date = TRTSDT,
event_conditions = list(ttae),
censor_conditions = list(eot),
source_datasets = list(adsl = adsl, ae = arrange(ae, desc(AESEQ))),
set_values_to = exprs(PARAMCD = "TTAE")
)

# Validate that the results are the same
expect_equal(result_sorted, result_unsorted, ignore_attr = TRUE)
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved
})

# Test 17: "derive_param_tte produces expected output for common scenario"
test_that("derive_param_tte produces expected output for common scenario", {
ProfessorP-beep marked this conversation as resolved.
Show resolved Hide resolved
# Define ADSL dataset
adsl <- tibble::tribble(
~USUBJID, ~TRTSDT, ~TRTEDT, ~EOSDT,
"01", ymd("2020-12-06"), ymd("2021-03-02"), ymd("2021-03-06"),
"02", ymd("2021-01-16"), ymd("2021-01-20"), ymd("2021-02-03")
) %>%
mutate(STUDYID = "AB42")

# Define AE dataset
ae <- tibble::tribble(
~USUBJID, ~AESTDTC, ~AESEQ, ~AEDECOD,
"01", "2021-01-03", 1, "Flu",
"01", "2021-03-04", 2, "Cough"
) %>%
mutate(
STUDYID = "AB42",
AESTDT = ymd(AESTDTC)
)

# Define event and censor sources
ttae <- event_source(
dataset_name = "ae",
date = AESTDT,
set_values_to = exprs(
EVENTDESC = "AE",
SRCDOM = "AE",
SRCVAR = "AESTDTC",
SRCSEQ = AESEQ
)
)

eot <- censor_source(
dataset_name = "adsl",
date = pmin(TRTEDT + days(10), EOSDT),
censor = 1,
set_values_to = exprs(
EVENTDESC = "END OF TRT",
SRCDOM = "ADSL",
SRCVAR = "TRTEDT"
)
)

# Run derive_param_tte
result <- derive_param_tte(
dataset_adsl = adsl,
start_date = TRTSDT,
event_conditions = list(ttae),
censor_conditions = list(eot),
source_datasets = list(adsl = adsl, ae = ae),
set_values_to = exprs(PARAMCD = "TTAE")
)

# Expected result
expected <- tibble::tibble(
USUBJID = c("01", "02"),
STUDYID = "AB42",
EVENTDESC = c("AE", "END OF TRT"),
SRCDOM = c("AE", "ADSL"),
SRCVAR = c("AESTDTC", "TRTEDT"),
SRCSEQ = c(1, NA),
CNSR = c(0, 1),
ADT = as.Date(c("2021-01-03", "2021-01-30")),
STARTDT = as.Date(c("2020-12-06", "2021-01-16")),
PARAMCD = "TTAE"
)

# Validate output
expect_equal(result, expected, ignore_attr = TRUE)
})