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.

Publication-Ready Visualisation

Overview

Two functions produce publication-ready figures and tables with minimal post-processing:

Function Output Typical use
plot_forest() Forest plot (PNG / PDF / JPG / TIFF) Regression results from assoc_*()
plot_tableone() Table 1 (DOCX / HTML / PDF / PNG) Baseline characteristics

When save = TRUE, both functions write all supported formats in a single call and return the plot/table object invisibly for further customisation.


plot_forest() — Forest Plot

Minimal example

plot_forest() takes a data frame whose first column is the row label, plus any additional display columns. The CI graphic and formatted OR (95% CI) text column are inserted automatically.

library(ukbflow)

df <- data.frame(
  item      = c("Exposure vs. control", "Unadjusted", "Fully adjusted"),
  `Cases/N` = c("", "89 / 4 521", "89 / 4 521"),
  p_value   = c(NA_real_, 0.001, 0.006),
  check.names = FALSE
)

p <- plot_forest(
  data      = df,
  est       = c(NA,   1.52, 1.43),
  lower     = c(NA,   1.18, 1.11),
  upper     = c(NA,   1.96, 1.85),
  ci_column = 3L,
  indent    = c(0L,   1L,   1L),
  p_cols    = "p_value",
  xlim      = c(0.5,  3.0)
)
plot(p)

Building the input data frame from assoc_*() results

The output of assoc_coxph() (and siblings) can be reshaped directly into the format expected by plot_forest():

dt  <- ops_toy(scenario = "association")
dt  <- dt[dm_timing != 1L]

res <- assoc_coxph(
  data         = dt,
  outcome_col  = "dm_status",
  time_col     = "dm_followup_years",
  exposure_col = "p20116_i0",
  covariates   = c("bmi_cat", "tdi_cat", "p1558_i0")
)
res <- as.data.frame(res)

# Reshape: one row per model, label column first
df2 <- data.frame(
  item    = c("Smoking status", as.character(res$model)),
  `N`     = c("", paste0(res$n, " / ", res$n_events)),
  p_value = c(NA_real_, res$p_value),
  check.names = FALSE
)

p <- plot_forest(
  data      = df2,
  est       = c(NA,   res$HR),
  lower     = c(NA,   res$CI_lower),
  upper     = c(NA,   res$CI_upper),
  ci_column = 3L,
  indent    = c(0L,   rep(1L, nrow(res))),
  p_cols    = "p_value",
  xlim      = c(0.5,  2.5)
)
plot(p)

Key parameters

CI appearance

# uses df, est, lower, upper from the minimal example above
p <- plot_forest(
  data      = df,
  est       = est, lower = lower, upper = upper,
  ci_column = 3L,
  ci_col    = c("grey50", "steelblue", "steelblue"),  # per-row colours
  ci_sizes  = 0.5,       # point size
  ci_Theight = 0.15,     # cap height
  ref_line  = 1,         # reference line (use 0 for beta coefficients)
  xlim      = c(0.2, 5), ticks_at = c(0.5, 1, 2, 3)
)

Row labels and indentation

# indent = 0 → bold parent row; indent >= 1 → indented sub-row (plain)
p <- plot_forest(
  data       = df,
  est        = est, lower = lower, upper = upper,
  ci_column  = 3L,
  indent     = c(0L, 1L, 1L),        # parent + 2 sub-rows
  bold_label = c(TRUE, FALSE, FALSE)  # explicit control (overrides indent default)
)

P-value formatting

# p_cols: column names in data that contain raw numeric p-values.
# Values < 10^(-p_digits) are displayed as e.g. "<0.001".
# bold_p = TRUE bolds all p < p_threshold (default 0.05).
p <- plot_forest(
  data        = df,
  est         = est, lower = lower, upper = upper,
  ci_column   = 3L,
  p_cols      = "p_value",
  p_digits    = 3L,
  bold_p      = TRUE,
  p_threshold = 0.05
)

Column headers and alignment

header renames all columns in the final rendered table. The final table always has ncol(data) + 2 columns: the original columns, plus the gap_ci graphic column and the auto-generated OR (95% CI) text column. Pass "" for the gap column position.

# data has 3 columns → final table has 5 columns (original 3 + gap_ci + OR label)
# Layout with ci_column = 3L: item | Cases/N | gap_ci | OR (95% CI) | p_value
p <- plot_forest(
  data      = df,
  est       = est, lower = lower, upper = upper,
  ci_column = 3L,
  header    = c("Comparison", "Cases / N", "", "HR (95% CI)", "P-value")
  #             col 1          col 2        gap  OR label       col 5
)

align controls per-column text alignment across all ncol(data) + 2 columns: -1 = left, 0 = centre, 1 = right. NULL (default) left-aligns column 1 and centres the rest.

p <- plot_forest(
  data      = df,
  est       = est, lower = lower, upper = upper,
  ci_column = 3L,
  align     = c(-1L, 0L, 0L, 0L, 1L)   # label left | Cases/N centre | gap | OR centre | p right
)

Background and borders

p <- plot_forest(
  data       = df,
  est        = est, lower = lower, upper = upper,
  ci_column  = 3L,
  background = "zebra",       # "zebra" | "bold_label" | "none"
  bg_col     = "#F0F0F0",     # shading colour
  border     = "three_line",  # "three_line" | "none"
  border_width = 3            # scalar or length-3 vector (top / mid / bottom)
)

Layout and saving

# uses df, est, lower, upper from the minimal example above
p <- plot_forest(
  data        = df,
  est         = est, lower = lower, upper = upper,
  ci_column   = 3L,
  row_height  = NULL,   # auto (8 / 12 / 10 / 15 mm); or scalar/vector
  col_width   = NULL,   # auto (rounds up to nearest 5 mm)
  save        = TRUE,
  dest        = "forest_main",   # extension ignored; all 4 formats saved
  save_width  = 20,              # cm
  save_height = NULL             # auto: nrow(data) * 0.9 + 3 cm
)

All four formats (PNG, PDF, JPG, TIFF) are written at 300 dpi with a white background. The function returns the plot object invisibly; display with plot(p) or grid::grid.draw(p).


plot_tableone() — Baseline Characteristics Table

Minimal example

library(gtsummary)
data(trial)   # built-in gtsummary dataset

plot_tableone(
  data   = trial,
  vars   = c("age", "marker", "grade"),
  strata = "trt",
  save   = FALSE
)

With SMD, custom labels, and export

plot_tableone(
  data    = trial,
  vars    = c("age", "marker", "grade", "stage"),
  strata  = "trt",
  label   = list(age ~ "Age (years)", marker ~ "Marker level (ng/mL)"),
  add_p   = TRUE,    # Wilcoxon / chi-squared p-values; formatted as <0.001
  add_smd = TRUE,
  overall = TRUE,
  dest    = "table1",
  save    = TRUE
)

Key parameters

Variable types and statistics

dt <- as.data.frame(ops_toy(scenario = "association"))

plot_tableone(
  data      = dt,
  vars      = c("p21022", "p21001_i0", "p31", "p20116_i0"),
  strata    = "dm_status",
  type      = list(p21022 = "continuous2"),   # show median + IQR
  statistic = list(
    all_continuous()  ~ "{mean} ({sd})",
    all_categorical() ~ "{n} ({p}%)"
  ),
  digits    = list(p21022 ~ 1, p21001_i0 ~ 1),
  missing   = "ifany",   # show missing counts when present
  save      = FALSE
)

SMD column

The SMD column summarises covariate balance between groups: - Continuous variables: Cohen’s d (pooled-SD formula) - Categorical variables: RMSD of group proportions

plot_tableone(
  data    = dt,
  vars    = c("p21022", "p21001_i0", "p31"),
  strata  = "dm_status",
  add_smd = TRUE,
  save    = FALSE
)

Excluding rows

Use exclude_labels to remove specific level rows from the rendered table (e.g. a redundant reference category or an “Unknown” level):

plot_tableone(
  data           = dt,
  vars           = c("p31", "p20116_i0"),
  strata         = "dm_status",
  exclude_labels = "Never",   # e.g. remove reference category from display
  save           = FALSE
)

Export formats

When save = TRUE, four files are written simultaneously:

Format Tool Notes
.docx gt::gtsave() Ready for Word submission
.html gt::gtsave() Interactive preview
.pdf pagedown::chrome_print() Requires Chrome / Chromium
.png webshot2::webshot() 2x zoom, table element only

PDF and PNG rendering requires pagedown and webshot2 respectively. Install with install.packages(c("pagedown", "webshot2")).


Getting Help

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.