The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
Many clinical tables require statistics computed relative to a
reference (control) group — for example, a risk difference versus
placebo. In rtables, the reference group can be injected
automatically via .ref_group and .in_ref_col,
but this breaks down when:
split_cols_by_multivar is present, oradd_overall_col is used alongside treatment
splits.get_ref_info() solves this by letting the analysis
function look up the reference group itself, using an explicit column
path (ref_path).
ref_path Conventionref_path is a character vector of alternating
split-variable names and their values, following the same convention as
rtables::col_paths():
c("var1", "level1", "var2", "level2", ...)
For a simple layout with split_cols_by("ARM"), the
placebo reference path is:
For a layout with a spanning header variable colspan_trt
above ARM, the path must include both levels:
The path must exactly match the column-split hierarchy in the layout.
Use col_paths(build_table(lyt, df)) to inspect the
available paths.
get_ref_info() returns a list with two elements:
in_ref_col: TRUE if the current column
matches ref_path, FALSE otherwise,
NULL if the reference split variable is not present in the
current column hierarchy.ref_group: the subset of the row data belonging to the
reference group (a data frame, or a vector if .var is
supplied).This example demonstrates the standard pattern for a table with
spanning headers and risk difference columns — the primary use case for
get_ref_info().
trtvar <- "TRT01A"
ctrl_grp <- "Placebo"
adsl <- pharmaverseadamjnj::adsl |>
filter(SAFFL == "Y") |>
select(STUDYID, USUBJID, all_of(trtvar), SAFFL) |>
mutate(!!trtvar := factor(
.data[[trtvar]],
levels = c("Xanomeline Low Dose", "Xanomeline High Dose", "Placebo")
))
adae <- pharmaverseadamjnj::adae |>
filter(TRTEMFL == "Y") |>
select(USUBJID, TRTEMFL, AEBODSYS, AEDECOD)
# Add spanning header and risk difference variables
adsl$colspan_trt <- factor(
ifelse(adsl[[trtvar]] == ctrl_grp, " ", "Active Study Agent"),
levels = c("Active Study Agent", " ")
)
adsl$rrisk_header <- "Risk Difference (%) (95% CI)"
adsl$rrisk_label <- paste(adsl[[trtvar]], "vs", ctrl_grp)
ae <- adae |> right_join(adsl, by = "USUBJID")The ref_path must trace the full column-split hierarchy
down to the reference group:
colspan_trt_map <- create_colspan_map(
adsl,
non_active_grp = ctrl_grp,
non_active_grp_span_lbl = " ",
active_grp_span_lbl = "Active Study Agent",
colspan_var = "colspan_trt",
trt_var = trtvar
)
ref_path <- c("colspan_trt", " ", trtvar, ctrl_grp)Now build the layout. The key point: a_freq_j uses
get_ref_info() internally to identify the reference group
and compute risk differences in the dedicated difference columns:
extra_args <- list(
denom = "n_altdf",
riskdiff = TRUE,
ref_path = ref_path,
method = "wald",
.stats = "count_unique_fraction",
.formats = c(rr_ci_3d = jjcsformat_xx("xx.x (xx.x, xx.x)"))
)
lyt <- basic_table(show_colcounts = TRUE, colcount_format = "N=xx") |>
split_cols_by("colspan_trt",
split_fun = trim_levels_to_map(map = colspan_trt_map)
) |>
split_cols_by(trtvar) |>
split_cols_by("rrisk_header", nested = FALSE) |>
split_cols_by(trtvar,
labels_var = "rrisk_label",
split_fun = remove_split_levels(ctrl_grp)
) |>
analyze("TRTEMFL",
afun = a_freq_j,
extra_args = append(extra_args, list(val = "Y", label = "Subjects with >=1 AE"))
) |>
split_rows_by("AEBODSYS",
split_label = "System Organ Class",
split_fun = trim_levels_in_group("AEDECOD"),
label_pos = "topleft",
section_div = " ",
nested = FALSE
) |>
summarize_row_groups("AEBODSYS", cfun = a_freq_j, extra_args = extra_args) |>
analyze("AEDECOD", afun = a_freq_j, extra_args = extra_args) |>
append_topleft(" Preferred Term, n (%)")
result <- build_table(lyt, ae, alt_counts_df = adsl)
head(result, 10)
#> Active Study Agent Risk Difference (%) (95% CI)
#> System Organ Class Xanomeline Low Dose Xanomeline High Dose Placebo Xanomeline Low Dose vs Placebo Xanomeline High Dose vs Placebo
#> Preferred Term, n (%) N=67 N=51 N=64 N=67 N=51
#> ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#> Subjects with >=1 AE 56 (83.6%) 48 (94.1%) 49 (76.6%) 7.0 (-6.6, 20.7) 17.6 (5.3, 29.8)
#> Cardiac disorders 10 (14.9%) 10 (19.6%) 9 (14.1%) 0.9 (-11.2, 12.9) 5.5 (-8.3, 19.4)
#> Atrial fibrillation 1 (1.5%) 1 (2.0%) 1 (1.6%) -0.1 (-4.3, 4.1) 0.4 (-4.5, 5.3)
#> Atrial flutter 1 (1.5%) 1 (2.0%) 0 1.5 (-1.4, 4.4) 2.0 (-1.8, 5.8)
#> Atrial hypertrophy 0 0 1 (1.6%) -1.6 (-4.6, 1.5) -1.6 (-4.6, 1.5)
#> Atrioventricular block first degree 1 (1.5%) 0 0 1.5 (-1.4, 4.4) 0.0 (0.0, 0.0)
#> Atrioventricular block second degree 0 0 1 (1.6%) -1.6 (-4.6, 1.5) -1.6 (-4.6, 1.5)
#> Bradycardia 0 0 1 (1.6%) -1.6 (-4.6, 1.5) -1.6 (-4.6, 1.5)
#> Bundle branch block left 0 0 1 (1.6%) -1.6 (-4.6, 1.5) -1.6 (-4.6, 1.5)
#> Bundle branch block right 1 (1.5%) 0 1 (1.6%) -0.1 (-4.3, 4.1) -1.6 (-4.6, 1.5)get_ref_info Works InternallyWhen a_freq_j (or any analysis function) calls
get_ref_info(ref_path, .spl_context):
ref_path are
present in the current column hierarchy (using in_column()
with wildcards)..spl_context.in_ref_col = TRUE/FALSE indicating whether
the current column IS the reference column (so the function can skip
computing a difference against itself).When the reference split is absent from the current column hierarchy
(e.g. in an add_overall_col("Total") column), both
in_ref_col and ref_group are
NULL.
in_column()in_column() — the underlying helper used by
get_ref_info() — supports "*" as a wildcard
for any single split variable name or value:
# Simulate a split context for ARM == "B: Placebo" under colspan_trt == " "
spl_ctx <- data.frame(
cur_col_split = I(list(c("colspan_trt", "ARM"))),
cur_col_split_val = I(list(c(" ", "B: Placebo")))
)
# Exact match
in_column(c("colspan_trt", " ", "ARM", "B: Placebo"), spl_ctx)
#> [1] TRUE
# Wildcard on spanning header — still TRUE
in_column(c("*", "*", "ARM", "B: Placebo"), spl_ctx)
#> [1] TRUE
# Different ARM level — FALSE
in_column(c("*", "*", "ARM", "A: Drug X"), spl_ctx)
#> [1] FALSEh_get_cur_trt_grpget_ref_info() and h_get_cur_trt_grp()
serve different purposes:
get_ref_info() |
h_get_cur_trt_grp() |
|
|---|---|---|
| Returns | reference-group data + in_ref_col flag |
current treatment group value (single string) |
| Used for | obtaining .ref_group / .in_ref_col for
statistics |
identifying which treatment group the current column belongs to |
| Typical callers | a_freq_j, a_eair_j,
s_ancova_j |
a_summarize_aval_chg_diff_j, a_freq_j,
a_freq_resp_var_j |
In layouts that combine split_cols_by_multivar with
difference columns, h_get_cur_trt_grp() resolves the
current treatment group from the interleaved column path, and
get_ref_info() obtains the reference-group data.
When constructing ref_path, inspect the column paths of
a built table:
col_paths(result)
#> [[1]]
#> [1] "colspan_trt" "Active Study Agent" "TRT01A"
#> [4] "Xanomeline Low Dose"
#>
#> [[2]]
#> [1] "colspan_trt" "Active Study Agent" "TRT01A"
#> [4] "Xanomeline High Dose"
#>
#> [[3]]
#> [1] "colspan_trt" " " "TRT01A" "Placebo"
#>
#> [[4]]
#> [1] "rrisk_header" "Risk Difference (%) (95% CI)"
#> [3] "TRT01A" "Xanomeline Low Dose"
#>
#> [[5]]
#> [1] "rrisk_header" "Risk Difference (%) (95% CI)"
#> [3] "TRT01A" "Xanomeline High Dose"Each path corresponds to a leaf column. The ref_path
should match one of these paths exactly (or a prefix thereof when the
reference column has further nested splits below it).
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.