Builds a results table in the manner of the rifttable package: a design
data frame names one estimand per row (counts, risks, rates, means,
survival, and model-based ratios and differences), and the table shows
each estimand for every level of an exposure, so that the descriptive
data and the comparative estimates sit in one table, as Rothman (2017)
asks. The design vocabulary is rifttable's: a design written for
rifttable::rifttable() builds the same table here, computed in base R
(plus survival for the event-time rows), and the result is an ltsummary
table, so modify_header(), bold_labels(), inline_text() and
as_lt() apply. See tbl_rift_design for every column of the design and
every type, and the
tbl_rift() tutorial.
Usage
tbl_rift(
design,
data,
id = "",
layout = c("rows", "cols"),
factor = 1000,
risk_percent = FALSE,
risk_digits = if (risk_percent) 0 else 2,
diff_digits = 2,
ratio_digits = 2,
ratio_digits_decrease = c(`2.995` = -1, `9.95` = -2),
rate_digits = 1,
to = NULL,
reference = "(reference)",
type2_layout = c("rows", "columns"),
overall = FALSE,
exposure_levels = c("noempty", "nona", "all"),
conf.level = 0.95
)Arguments
- design
(
data.frame)
One row per table row, with at least atypecolumn; the other columns are described in tbl_rift_design.- data
(
data.frame)
The data the design refers to.- id
(
string)
Reserved for clustered observations; only""(the default) is supported in this version.- layout
(
string)
Only"rows"(the design as rows, the exposure levels as columns) is supported in this version.- factor
(
scalar numeric)
Rates are reported per this much person-time. Default is1000.- risk_percent
(
scalar logical)
Whether risks, cumulative incidences, survival probabilities and their differences are shown as percentages. Default isFALSE.- risk_digits, diff_digits, ratio_digits, rate_digits
(
integer)
Decimal places of risks (default2, or0withrisk_percent), of means and differences (2), of ratios (2) and of rates (1). Adigitscolumn of the design overrides them row by row.- ratio_digits_decrease
(named
numeric)
Fewer decimals for large ratios: by default one fewer at or above2.995and two fewer at or above9.95, so ratios read1.23,3.5and12.NULLkeepsratio_digitseverywhere.- to
(
string)
The separator between confidence limits and between the bounds of a range. Default is thepkgwide-str:ci.septheme element,", "unless a theme sets it. Atocolumn of the design overrides it.- reference
(
string)
The text after the null value in the cell of the reference level. Default is"(reference)", giving"1 (reference)"for ratios and"0 (reference)"for differences.- type2_layout
(
string)
Reserved for a second estimand per row (type2), not supported in this version.- overall
(
scalar logical)
Whether a first column shows the descriptive estimands over all exposure levels. Default isFALSE;add_overall()adds the column later.- exposure_levels
(
string)
Which levels of the exposure become columns:"noempty"(the default), the levels present in the data plus a column for missing values when there are any;"nona", the same without the missing values; or"all", every level of the factor.- conf.level
(
scalar numeric)
The confidence level of every interval. Default is0.95. Acicolumn of the design overrides it row by row.
Value
A table of class c("tbl_rift", "ltsummary"). The body has one
row per design row, with the level rows (labels starting with two
spaces) indented, one column per exposure level (stat_1, stat_2,
...), stat_0 for the overall column and trend for the slope column.
The numbers behind every cell are in x$stats$tbl_rift, and
inline_text() reads them: inline_text(x, variable = "Risk ratio", column = "Drug B", pattern = "{estimate} ({conf.low}, {conf.high})").
Differences from rifttable
Numbers are rounded half away from zero with the theme's decimal and big
marks. A continuous exposure is an error rather than a warning. The
reference level's mean interval is the normal interval, as in rifttable,
where add_ci() uses the t interval. Cumulative-incidence contrasts pair
each level's own limits as Zou and Donner (2008) describe; rifttable does
the same from version 0.7.3, and versions up to 0.7.2 mirror the interval
about the estimate. Models that do not converge, or cannot be fit, show
"--" and the message is reported once after the table is built. Custom
estimate_*() functions, type2, layout = "cols", weights and id
are not available in this version.
References
Rothman KJ. The growing rift between epidemiologists and their data. Eur J Epidemiol 2017;32:863-5.
Stopsack KH. rifttable: Results tables to bridge the rift between epidemiologists and their data. R package, https://stopsack.github.io/rifttable/.
See also
tbl_rift_design for the design vocabulary; rift_risk,
rift_survival and rift_rate() for the estimators on their own.
Other results tables:
rift_rate(),
rift_risk,
rift_survival,
tbl_rift_design
Other table builders:
tbl_continuous(),
tbl_cross(),
tbl_custom_summary(),
tbl_likert(),
tbl_merge(),
tbl_regression(),
tbl_stack(),
tbl_strata(),
tbl_strata_nested_stack(),
tbl_summary(),
tbl_survfit(),
tbl_uvregression(),
tbl_wide_summary()
Examples
# Example 1 ----------------------------------
# tumor response by treatment: the counts, the risk, and two contrasts
design <- data.frame(
label = c("Responders/N", "Risk (95% CI)", "Risk ratio (95% CI)", "Risk difference (95% CI)"),
type = c("outcomes/total", "risk (ci)", "rr", "rd"),
exposure = "trt",
outcome = "response"
)
tbl_rift(design, trial, risk_percent = TRUE)
# Example 2 ----------------------------------
# a design with section headers, indented rows, an effect modifier and a
# joint model, in rifttable's own notation
design2 <- data.frame(
label = c("**All patients**", " Deaths/N", " Rate per 100 months (95% CI)",
" Hazard ratio (95% CI)", " Age-adjusted HR (95% CI)", "",
"**Grade I**", " Deaths/N", " Hazard ratio (95% CI)",
"**Joint model**", " Grade I", " Grade II"),
type = c("", "events/total", "rate (ci)", "hr", "hr", "",
"", "events/total", "hr", "", "hr_joint", "hr_joint"),
confounders = c("", "", "", "", "+ age", "", "", "", "", "", "", ""),
effect_modifier = c(NA, NA, NA, NA, NA, NA, "grade", "grade", "grade", NA, "grade", "grade"),
stratum = c(NA, NA, NA, NA, NA, NA, "I", "I", "I", NA, "I", "II")
)
design2$exposure <- "trt"
design2$time <- "ttdeath"
design2$event <- "death"
if (requireNamespace("survival", quietly = TRUE)) {
tbl_rift(design2, trial, factor = 100) |>
add_overall()
}
# Example 3 ----------------------------------
# a continuous outcome with a per-unit trend and a time point for survival
design3 <- data.frame(
label = c("Mean age (SD)", "Difference in age (95% CI)", "12-month survival (95% CI)",
"Difference in 12-month survival"),
type = c("mean (sd)", "diff", "surv (ci)", "survdiff"),
outcome = c("age", "age", NA, NA),
time = c(NA, NA, "ttdeath", "ttdeath"),
event = c(NA, NA, "death", "death"),
exposure = "grade",
digits = c(1, 1, 2, 2)
)
design3$arguments <- list(NULL, NULL, list(timepoint = 12), list(timepoint = 12))
if (requireNamespace("survival", quietly = TRUE)) {
tbl_rift(design3, trial)
}