Skip to content

Commit

Permalink
335 differential precision (chevron) (#343)
Browse files Browse the repository at this point in the history
close #335 
This is a proof of concept applied to lbt01
- add precision arguments
- put a blank in baseline CHG cell

thank you for your suggestions

Signed-off-by: Liming <[email protected]>
Co-authored-by: benoit <[email protected]>
Co-authored-by: Liming <[email protected]>
  • Loading branch information
3 people authored Jan 13, 2023
1 parent 6475d78 commit 5960712
Show file tree
Hide file tree
Showing 19 changed files with 2,122 additions and 267 deletions.
3 changes: 3 additions & 0 deletions NAMESPACE
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export(get_adam_datasets)
export(get_main)
export(get_postprocess)
export(get_preprocess)
export(h_format_dec)
export(lbt01_1)
export(lbt01_1_lyt)
export(lbt01_1_main)
Expand Down Expand Up @@ -211,6 +212,8 @@ importFrom(methods,setValidity)
importFrom(rlang,.data)
importFrom(rlang,.env)
importFrom(rlang,sym)
importFrom(stats,median)
importFrom(stats,sd)
importFrom(stats,setNames)
importFrom(tibble,tribble)
importFrom(yaml,read_yaml)
71 changes: 64 additions & 7 deletions R/lbt01.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#' @param summaryvars (named vector of `character`) variables to be analyzed. Names are used as subtitles. For values
#' where no name is provided, the label attribute of the corresponding column in `adlb` table of `adam_db` is used.
#' @param visitvar (`character`) the type of time point to use. Typically one of `"AVISIT"` (Default) or `"ATPTN"`.
#' @param precision (named vector of `integer`) where names are values found in the `PARAMCD` column and the the values
#' indicate the number of digits that should be represented for `min`, `max` and `median`. `Mean` and `sd` are
#' represented with one more decimal of precision.
#' @param default_precision (`integer`) the default number of digits.
#'
#' @details
#' * The `Analysis Value` column, displays the number of patients, the mean, standard deviation, median and range of
Expand All @@ -27,8 +31,16 @@ lbt01_1_main <- function(adam_db,
armvar = "ACTARM",
summaryvars = c("Value at Visit" = "AVAL", "Change from \nBaseline" = "CHG"),
visitvar = "AVISIT",
precision = integer(),
default_precision = 2,
deco = std_deco("LBT01"),
...) {
assert_colnames(adam_db$adlb, c("PARAM", "PARAMCD"))
assert_colnames(adam_db$adlb, summaryvars)
assert_colnames(adam_db$adlb, armvar)
assert_colnames(adam_db$adlb, visitvar)
checkmate::assert_integerish(precision, lower = 0)

lbl_avisit <- var_labels_for(adam_db$adlb, visitvar)
lbl_param <- var_labels_for(adam_db$adlb, "PARAM")

Expand All @@ -42,6 +54,8 @@ lbt01_1_main <- function(adam_db,
lbl_avisit = lbl_avisit,
lbl_param = lbl_param,
deco = deco,
precision = precision,
default_precision = default_precision,
... = ...
)

Expand All @@ -52,7 +66,7 @@ lbt01_1_main <- function(adam_db,

#' @describeIn lbt01_1 Layout
#'
#' @inheritParams gen_args
#' @inheritParams lbt01_1_main
#'
#' @param summaryvars (`vector of character`) the variables to be analyzed. For this table, `AVAL` and `CHG` by default.
#' @param summaryvars_lbls (`vector of character`) the label of the variables to be analyzed.
Expand All @@ -71,14 +85,14 @@ lbt01_1_lyt <- function(armvar,
lbl_avisit,
lbl_param,
deco,
precision,
default_precision,
...) {
# TODO solve the problem of the overall column
# remove change from baseline in BASELINE

basic_table_deco(deco) %>%
split_cols_by(armvar) %>%
split_rows_by(
"PARAM",
var = "PARAMCD",
labels_var = "PARAM",
split_fun = drop_split_levels,
label_pos = "hidden",
split_label = paste(lbl_param)
Expand All @@ -94,7 +108,47 @@ lbt01_1_lyt <- function(armvar,
varlabels = summaryvars_lbls,
nested = TRUE
) %>%
summarize_colvars() %>%
analyze_colvars(
afun = function(x, .var, .spl_context, precision, default_precision, ...) {
param_val <- .spl_context$value[1]
pcs <- precision[param_val]

pcs <- ifelse(is.na(pcs), default_precision, pcs)

# Create context dependent function.
n_fun <- sum(!is.na(x), na.rm = TRUE)
mean_sd_fun <- c(mean(x, na.rm = TRUE), sd(x, na.rm = TRUE))
median_fun <- median(x, na.rm = TRUE)
min_max_fun <- c(min(x), max(x))

# Identify context-
is_baseline <- .spl_context$value[2] == "BASELINE"
is_chg <- .var == "CHG"

is_baseline <- .spl_context$value[which(.spl_context$split == "AVISIT")] == "BASELINE"

if (is_baseline && is_chg) {
n_fun <- mean_sd_fun <- median_fun <- min_max_fun <- NULL
}

in_rows(
"n" = n_fun,
"Mean (SD)" = mean_sd_fun,
"Median" = median_fun,
"Min - Max" = min_max_fun,
.formats = list(
"n" = "xx",
"Mean (SD)" = h_format_dec(format = "%f (%f)", digits = pcs + 1),
"Median" = h_format_dec(format = "%f", digits = pcs + 1),
"Min - Max" = h_format_dec(format = "%f - %f", digits = pcs)
)
)
},
extra_args = list(
precision = precision,
default_precision = default_precision
)
) %>%
append_topleft(paste(lbl_param)) %>%
append_topleft(c(paste(" ", lbl_avisit), " "))
}
Expand Down Expand Up @@ -136,7 +190,10 @@ lbt01_1_post <- function(tlg, prune_0 = TRUE, ...) {
#' @export
#'
#' @examples
#' run(lbt01_1, syn_data)
#' run(lbt01_1, syn_data, precision = c(
#' "ALT" = 0,
#' "CRP" = 1
#' ))
lbt01_1 <- chevron_t(
main = lbt01_1_main,
preprocess = lbt01_1_pre,
Expand Down
2 changes: 1 addition & 1 deletion R/package.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#' @importFrom magrittr %>%
#' @importFrom methods is setValidity
#' @importFrom rlang sym .data .env
#' @importFrom stats setNames
#' @importFrom stats setNames median sd
#' @importFrom tibble tribble
#' @importFrom yaml read_yaml
"_PACKAGE"
36 changes: 36 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,39 @@ std_postprocess <- function(tlg, ind = 2L, ...) {

res
}

# Special formats ----

#' Decimal Formatting
#'
#' @param digits (`integer`) number of digits.
#' @param format (`string`) describing how the numbers should be formatted following the `sprintf` syntax.
#'
#' @return `function` formatting numbers with the defined format or `NULL` if the format is not defined.
#'
#' @export
#'
#' @examples
#' fun <- h_format_dec(1, "%f - %f")
#' fun(c(123, 567.89))
#'
h_format_dec <- function(digits = NA, format = NA) {
checkmate::assert_integerish(digits, lower = 0, len = 1)
checkmate::assert_string(format, na.ok = TRUE)

if (is.na(format)) {
NULL

} else {

function(x, ...) {
checkmate::assert_numeric(x)

digit_string <- ifelse(is.na(digits), "", paste0(".", digits))
new_format <- gsub("%([a-z])", paste0("%", digit_string, "\\1"), format)
fun <- formatters::sprintf_format(new_format)

fun(x)
}
}
}
1 change: 1 addition & 0 deletions _pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ reference:
- std_deco
- syn_test_data
- var_labels_for
- h_format_dec

- title: Non-exported Documented Functions for Packagage Developers
contents:
Expand Down
24 changes: 24 additions & 0 deletions man/h_format_dec.Rd

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

15 changes: 14 additions & 1 deletion man/lbt01_1.Rd

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

10 changes: 5 additions & 5 deletions tests/testthat/_snaps/aet01.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
Total number of deaths 25 (18.7%) 23 (17.2%) 22 (16.7%)
Total number of patients withdrawn from study due to an AE 3 (2.2%) 6 (4.5%) 5 (3.8%)
Total number of patients with at least one
AE with fatal outcome 0 (0.0%) 0 (0.0%) 0 (0.0%)
Serious AE 0 (0.0%) 0 (0.0%) 0 (0.0%)
Serious AE leading to withdrawal from treatment 0 (0.0%) 0 (0.0%) 0 (0.0%)
Serious AE leading to dose modification/interruption 0 (0.0%) 0 (0.0%) 0 (0.0%)
Related Serious AE 0 (0.0%) 0 (0.0%) 0 (0.0%)
AE with fatal outcome 0 0 0
Serious AE 0 0 0
Serious AE leading to withdrawal from treatment 0 0 0
Serious AE leading to dose modification/interruption 0 0 0
Related Serious AE 0 0 0
AE leading to withdrawal from treatment 27 (20.1%) 26 (19.4%) 30 (22.7%)
AE leading to dose modification/interruption 66 (49.3%) 76 (56.7%) 74 (56.1%)
Related AE 105 (78.4%) 108 (80.6%) 109 (82.6%)
Expand Down
88 changes: 88 additions & 0 deletions tests/testthat/_snaps/aet03.new.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# aet03 can handle all NA values

Code
res
Output
AEBODSYS A: Drug X B: Placebo C: Combination
AEDECOD (N=134) (N=134) (N=132)
——————————————————————————————————————————————————————————————————
- Any Intensity - 122 (91.0%) 123 (91.8%) 120 (90.9%)
No Coding available
- Any Intensity - 122 (91.0%) 123 (91.8%) 120 (90.9%)
No Coding available
- Any Intensity - 122 (91.0%) 123 (91.8%) 120 (90.9%)

# aet03 can handle some NA values

Code
res
Output
AEBODSYS A: Drug X B: Placebo C: Combination
AEDECOD (N=134) (N=134) (N=132)
——————————————————————————————————————————————————————————————————
- Any Intensity - 122 (91.0%) 123 (91.8%) 120 (90.9%)
MILD 7 (5.2%) 9 (6.7%) 4 (3.0%)
MODERATE 23 (17.2%) 24 (17.9%) 23 (17.4%)
SEVERE 91 (67.9%) 90 (67.2%) 93 (70.5%)
<Missing> 1 (0.7%) 0 0
cl A.1
- Any Intensity - 78 (58.2%) 75 (56.0%) 89 (67.4%)
MILD 30 (22.4%) 27 (20.1%) 39 (29.5%)
MODERATE 48 (35.8%) 48 (35.8%) 50 (37.9%)
dcd A.1.1.1.1
- Any Intensity - 50 (37.3%) 45 (33.6%) 63 (47.7%)
MILD 50 (37.3%) 45 (33.6%) 63 (47.7%)
dcd A.1.1.1.2
- Any Intensity - 48 (35.8%) 48 (35.8%) 50 (37.9%)
MODERATE 48 (35.8%) 48 (35.8%) 50 (37.9%)
cl B.2
- Any Intensity - 78 (58.2%) 74 (55.2%) 85 (64.4%)
MILD 30 (22.4%) 30 (22.4%) 33 (25.0%)
MODERATE 48 (35.8%) 44 (32.8%) 52 (39.4%)
dcd B.2.2.3.1
- Any Intensity - 48 (35.8%) 54 (40.3%) 51 (38.6%)
MILD 48 (35.8%) 54 (40.3%) 51 (38.6%)
dcd B.2.1.2.1
- Any Intensity - 48 (35.8%) 44 (32.8%) 52 (39.4%)
MODERATE 48 (35.8%) 44 (32.8%) 52 (39.4%)
cl D.1
- Any Intensity - 78 (58.2%) 67 (50.0%) 80 (60.6%)
MODERATE 28 (20.9%) 25 (18.7%) 29 (22.0%)
SEVERE 50 (37.3%) 42 (31.3%) 51 (38.6%)
dcd D.1.1.1.1
- Any Intensity - 50 (37.3%) 42 (31.3%) 51 (38.6%)
SEVERE 50 (37.3%) 42 (31.3%) 51 (38.6%)
dcd D.1.1.4.2
- Any Intensity - 47 (35.1%) 42 (31.3%) 50 (37.9%)
MODERATE 47 (35.1%) 42 (31.3%) 50 (37.9%)
cl D.2
- Any Intensity - 47 (35.1%) 58 (43.3%) 57 (43.2%)
MILD 47 (35.1%) 58 (43.3%) 57 (43.2%)
dcd D.2.1.5.3
- Any Intensity - 47 (35.1%) 58 (43.3%) 57 (43.2%)
MILD 47 (35.1%) 58 (43.3%) 57 (43.2%)
cl B.1
- Any Intensity - 47 (35.1%) 49 (36.6%) 43 (32.6%)
SEVERE 47 (35.1%) 49 (36.6%) 43 (32.6%)
dcd B.1.1.1.1
- Any Intensity - 47 (35.1%) 49 (36.6%) 43 (32.6%)
SEVERE 47 (35.1%) 49 (36.6%) 43 (32.6%)
cl C.2
- Any Intensity - 35 (26.1%) 48 (35.8%) 55 (41.7%)
MODERATE 35 (26.1%) 48 (35.8%) 55 (41.7%)
dcd C.2.1.2.1
- Any Intensity - 35 (26.1%) 48 (35.8%) 55 (41.7%)
MODERATE 35 (26.1%) 48 (35.8%) 55 (41.7%)
cl C.1
- Any Intensity - 43 (32.1%) 46 (34.3%) 43 (32.6%)
SEVERE 43 (32.1%) 46 (34.3%) 43 (32.6%)
dcd C.1.1.1.3
- Any Intensity - 43 (32.1%) 46 (34.3%) 43 (32.6%)
SEVERE 43 (32.1%) 46 (34.3%) 43 (32.6%)
No Coding available
- Any Intensity - 1 (0.7%) 0 0
<Missing> 1 (0.7%) 0 0
No Coding available
- Any Intensity - 1 (0.7%) 0 0
<Missing> 1 (0.7%) 0 0

Loading

0 comments on commit 5960712

Please sign in to comment.