Skip to contents

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 a type column; 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 is 1000.

risk_percent

(scalar logical)
Whether risks, cumulative incidences, survival probabilities and their differences are shown as percentages. Default is FALSE.

risk_digits, diff_digits, ratio_digits, rate_digits

(integer)
Decimal places of risks (default 2, or 0 with risk_percent), of means and differences (2), of ratios (2) and of rates (1). A digits column of the design overrides them row by row.

ratio_digits_decrease

(named numeric)
Fewer decimals for large ratios: by default one fewer at or above 2.995 and two fewer at or above 9.95, so ratios read 1.23, 3.5 and 12. NULL keeps ratio_digits everywhere.

to

(string)
The separator between confidence limits and between the bounds of a range. Default is the pkgwide-str:ci.sep theme element, ", " unless a theme sets it. A to column 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 is FALSE; 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 is 0.95. A ci column 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/.

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) }