| Title: | Publication-Ready Forest Plots with 'ggplot2' |
|---|---|
| Description: | Transform model coefficients into flexible forest plots using 'ggplot2'. Provides helpers to standardize coefficient data from a range of modelling workflows and render publication-ready forest plots with a consistent interface. |
| Authors: | Carson Richardson [aut, cre, cph] (ORCID: <https://orcid.org/0009-0004-8710-1097>) |
| Maintainer: | Carson Richardson <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.5.0.9000 |
| Built: | 2026-09-27 19:00:19 UTC |
| Source: | https://github.com/thatoneguy006/ggforestplotr |
Compose a two-sided arrow annotation beneath the trained forest-plot x panel. The annotation is a separate footer plot, so it does not alter the forest plot's scales, limits, confidence intervals, or reference line.
add_favors( plot = NULL, left, right, reference = NULL, gap = 0.02, footer_height = 0.4, text_size = 3.2, linewidth = 0.5, arrow_length = 0.08, arrow_type = c("closed", "open") )add_favors( plot = NULL, left, right, reference = NULL, gap = 0.02, footer_height = 0.4, text_size = 3.2, linewidth = 0.5, arrow_length = 0.08, arrow_type = c("closed", "open") )
plot |
A plot created by |
left, right
|
Single strings shown beneath the left and right arrows. |
reference |
Optional numeric reference value. |
gap |
Gap on each side of the trained reference position, expressed as a fraction of the forest panel width. |
footer_height |
Footer height in inches. |
text_size |
Text size passed to |
linewidth |
Line width passed to |
arrow_length |
Arrowhead length in inches. |
arrow_type |
Whether arrowheads are |
add_favors() is designed as the final composition step. It works with a
bare ggforestplot() result and with layouts returned by
add_forest_table() and add_split_table().
A patchwork-composed plot with a footer beneath only the forest-plot
column, or a ggplot add-on object when plot = NULL.
coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.10, -0.08, 0.34), conf.low = c(0.02, -0.16, 0.12), conf.high = c(0.18, 0.00, 0.56) ) ggforestplot(coefs) + add_favors( left = "Treatment A better", right = "Treatment B better" ) add_favors( ggforestplot(coefs), left = "Treatment A better", right = "Treatment B better" )coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.10, -0.08, 0.34), conf.low = c(0.02, -0.16, 0.12), conf.high = c(0.18, 0.00, 0.56) ) ggforestplot(coefs) + add_favors( left = "Treatment A better", right = "Treatment B better" ) add_favors( ggforestplot(coefs), left = "Treatment A better", right = "Treatment B better" )
Compose a summary table onto a forest plot.
add_forest_table( plot = NULL, position = c("left", "right"), columns = NULL, term_header = "Term", n_header = "N", events_header = "Events", estimate_label = NULL, p_header = "P-value", column_labels = NULL, digits = NULL, estimate_digits = NULL, interval_digits = NULL, p_digits = NULL, estimate_fmt = NULL, ci_fmt = NULL, formatters = NULL, reference_text = "Reference", text_size = NULL, header_text_size = NULL, header_fontface = "bold", header_family = NULL, striped_rows = NULL, stripe_fill = NULL, stripe_colour = NULL, stripe_alpha = NULL, grid_lines = FALSE, grid_line_colour = "black", grid_line_size = 0.3, grid_line_linetype = 1, table_width = NULL, plot_width = NULL )add_forest_table( plot = NULL, position = c("left", "right"), columns = NULL, term_header = "Term", n_header = "N", events_header = "Events", estimate_label = NULL, p_header = "P-value", column_labels = NULL, digits = NULL, estimate_digits = NULL, interval_digits = NULL, p_digits = NULL, estimate_fmt = NULL, ci_fmt = NULL, formatters = NULL, reference_text = "Reference", text_size = NULL, header_text_size = NULL, header_fontface = "bold", header_family = NULL, striped_rows = NULL, stripe_fill = NULL, stripe_colour = NULL, stripe_alpha = NULL, grid_lines = FALSE, grid_line_colour = "black", grid_line_size = 0.3, grid_line_linetype = 1, table_width = NULL, plot_width = NULL )
plot |
A plot created by |
position |
Whether to place the table on the left or right of the forest plot. |
columns |
Optional explicit columns to display in the side table, in
the order they should appear. Accepts built-in names such as |
term_header |
Deprecated. Use the corresponding entry in
|
n_header |
Deprecated. Use
|
events_header |
Deprecated. Use
|
estimate_label |
Header label for the estimate column. Defaults to the model-derived label when available. |
p_header |
Deprecated. Use
|
column_labels |
Optional named vector used to relabel table column
headers. Names should match values supplied to |
digits |
Deprecated. Number of digits used when formatting estimates
and p-values. Defaults to |
estimate_digits |
Number of digits used for point estimates. |
interval_digits |
Number of digits used for confidence interval bounds. |
p_digits |
Number of digits used for p-values. |
estimate_fmt |
Format string for the estimate column. Use
|
ci_fmt |
Format string for the confidence interval column when
|
formatters |
Named list of vectorized functions for scalar table
values. Keys include |
reference_text |
Text shown in estimate cells for reference rows. |
text_size |
Text size for table contents. Defaults to |
header_text_size |
Header text size for table column labels. Defaults
to |
header_fontface |
Font face used for table column labels. Defaults to
|
header_family |
Optional font family used for table column labels. |
striped_rows |
Whether to draw alternating row stripes behind the
table. Defaults to the stripe setting used in |
stripe_fill |
Fill colour used for striped rows. Defaults to the
stripe fill used in |
stripe_colour |
Outline colour for striped rows. Defaults to the
stripe outline used in |
stripe_alpha |
Transparency for striped rows. Defaults to the stripe
alpha used in |
grid_lines |
Whether to draw black horizontal grid lines in the table. |
grid_line_colour |
Colour used for the table grid lines. |
grid_line_size |
Line width used for the table grid lines. |
grid_line_linetype |
Line type used for the table grid lines. |
table_width |
Optional relative width allocated to the table panel. By default this is calculated from the displayed table content. |
plot_width |
Optional relative width allocated to the forest-plot
panel. Defaults to |
A patchwork-composed plot containing the forest plot and side
table, or a ggplot add-on object when plot = NULL.
coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.3, -0.2, 0.4), conf.low = c(0.1, -0.4, 0.2), conf.high = c(0.5, 0.0, 0.6), sample_size = c(120, 115, 98), p_value = c(0.012, 0.031, 0.004) ) p <- ggforestplot(coefs, n = "sample_size", p.value = "p_value") add_forest_table( p, position = "left", columns = c("term", "n", "estimate", "p"), estimate_label = "Beta" ) ggforestplot(coefs, n = "sample_size", p.value = "p_value") + add_forest_table( position = "right", columns = c("term", "n", "estimate", "p"), estimate_label = "Beta" )coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.3, -0.2, 0.4), conf.low = c(0.1, -0.4, 0.2), conf.high = c(0.5, 0.0, 0.6), sample_size = c(120, 115, 98), p_value = c(0.012, 0.031, 0.004) ) p <- ggforestplot(coefs, n = "sample_size", p.value = "p_value") add_forest_table( p, position = "left", columns = c("term", "n", "estimate", "p"), estimate_label = "Beta" ) ggforestplot(coefs, n = "sample_size", p.value = "p_value") + add_forest_table( position = "right", columns = c("term", "n", "estimate", "p"), estimate_label = "Beta" )
Compose split table blocks around a forest plot so that summary data appear on both sides of the plotting panel.
add_split_table( plot = NULL, left_columns = NULL, right_columns = NULL, term_header = "Term", n_header = "N", events_header = "Events", estimate_label = NULL, p_header = "P-value", column_labels = NULL, digits = NULL, estimate_digits = NULL, interval_digits = NULL, p_digits = NULL, estimate_fmt = NULL, ci_fmt = NULL, formatters = NULL, reference_text = "Reference", text_size = NULL, header_text_size = NULL, header_fontface = "bold", header_family = NULL, striped_rows = NULL, stripe_fill = NULL, stripe_colour = NULL, stripe_alpha = NULL, left_width = NULL, plot_width = NULL, right_width = NULL )add_split_table( plot = NULL, left_columns = NULL, right_columns = NULL, term_header = "Term", n_header = "N", events_header = "Events", estimate_label = NULL, p_header = "P-value", column_labels = NULL, digits = NULL, estimate_digits = NULL, interval_digits = NULL, p_digits = NULL, estimate_fmt = NULL, ci_fmt = NULL, formatters = NULL, reference_text = "Reference", text_size = NULL, header_text_size = NULL, header_fontface = "bold", header_family = NULL, striped_rows = NULL, stripe_fill = NULL, stripe_colour = NULL, stripe_alpha = NULL, left_width = NULL, plot_width = NULL, right_width = NULL )
plot |
A plot created by |
left_columns |
Optional explicit columns to place on the left side of
the forest plot. Accepts built-in names such as |
right_columns |
Optional explicit columns to place on the right side
of the forest plot. Accepts built-in names such as |
term_header |
Deprecated. Use the corresponding entry in
|
n_header |
Deprecated. Use
|
events_header |
Deprecated. Use
|
estimate_label |
Header label for the estimate column. Defaults to the model-derived label when available. |
p_header |
Deprecated. Use
|
column_labels |
Optional named vector used to relabel table column
headers. Names should match values supplied to |
digits |
Deprecated. Number of digits used when formatting estimates
and p-values. Defaults to |
estimate_digits |
Number of digits used for point estimates. |
interval_digits |
Number of digits used for confidence interval bounds. |
p_digits |
Number of digits used for p-values. |
estimate_fmt |
Format string for the estimate column. Use
|
ci_fmt |
Format string for the confidence interval column when
table columns include |
formatters |
Named list of vectorized functions for scalar table
values. Keys include |
reference_text |
Text shown in estimate cells for reference rows. |
text_size |
Text size for table contents. Defaults to |
header_text_size |
Header text size for table column labels. Defaults
to |
header_fontface |
Font face used for table column labels. Defaults to
|
header_family |
Optional font family used for table column labels. |
striped_rows |
Whether to draw alternating row stripes behind the
split table layout. Defaults to the stripe setting used in
|
stripe_fill |
Fill colour used for striped rows. Defaults to the
stripe fill used in |
stripe_colour |
Outline colour for striped rows. Defaults to the
stripe outline used in |
stripe_alpha |
Transparency for striped rows. Defaults to the stripe
alpha used in |
left_width |
Optional width allocated to the left table block. By
default this is derived from the number of displayed left-side columns
relative to |
plot_width |
Optional width allocated to the forest plot panel.
Defaults to |
right_width |
Optional width allocated to the right table block. By
default this is derived from the number of displayed right-side columns
relative to |
A patchwork-composed plot containing a left table, the forest plot,
and a right table, or a ggplot add-on object when plot = NULL.
coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.3, -0.2, 0.4), conf.low = c(0.1, -0.4, 0.2), conf.high = c(0.5, 0.0, 0.6), sample_size = c(120, 115, 98), p_value = c(0.012, 0.031, 0.004) ) p <- ggforestplot(coefs, n = "sample_size", p.value = "p_value") add_split_table( p, left_columns = c("term", "n"), right_columns = c("estimate", "p"), estimate_label = "HR" ) ggforestplot(coefs, n = "sample_size", p.value = "p_value") + add_split_table( left_columns = c(1, 5), right_columns = c(2, 6), estimate_label = "HR" )coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.3, -0.2, 0.4), conf.low = c(0.1, -0.4, 0.2), conf.high = c(0.5, 0.0, 0.6), sample_size = c(120, 115, 98), p_value = c(0.012, 0.031, 0.004) ) p <- ggforestplot(coefs, n = "sample_size", p.value = "p_value") add_split_table( p, left_columns = c("term", "n"), right_columns = c("estimate", "p"), estimate_label = "HR" ) ggforestplot(coefs, n = "sample_size", p.value = "p_value") + add_split_table( left_columns = c(1, 5), right_columns = c(2, 6), estimate_label = "HR" )
Standardizes a coefficient table into the internal forest-plot data
structure used throughout ggforestplotR.
as_forest_data(data, ...) ## S3 method for class 'forest_data' as_forest_data( data, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), exponentiate = NULL, p_method = NULL, ... ) ## S3 method for class 'data.frame' as_forest_data( data, term, estimate, conf.low, conf.high, label = term, term_labels = NULL, group = NULL, grouping = NULL, separate_groups = NULL, n = NULL, events = NULL, p.value = NULL, exponentiate = NULL, estimate_scale = NULL, axis_transform = NULL, effect_label = NULL, conf.level = 0.95, reference_value = NULL, source_model = NULL, source_package = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, p_method = c("overall", "level"), row_type = NULL, ... ) ## S3 method for class 'lm' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'glm' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'coxph' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'merMod' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'lme' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'glmmTMB' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## Default S3 method: as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") )as_forest_data(data, ...) ## S3 method for class 'forest_data' as_forest_data( data, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), exponentiate = NULL, p_method = NULL, ... ) ## S3 method for class 'data.frame' as_forest_data( data, term, estimate, conf.low, conf.high, label = term, term_labels = NULL, group = NULL, grouping = NULL, separate_groups = NULL, n = NULL, events = NULL, p.value = NULL, exponentiate = NULL, estimate_scale = NULL, axis_transform = NULL, effect_label = NULL, conf.level = 0.95, reference_value = NULL, source_model = NULL, source_package = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, p_method = c("overall", "level"), row_type = NULL, ... ) ## S3 method for class 'lm' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'glm' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'coxph' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'merMod' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'lme' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## S3 method for class 'glmmTMB' as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") ) ## Default S3 method: as_forest_data( data, ..., conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") )
data |
A data frame or data-frame subclass containing coefficient
estimates and intervals. Tibbles and |
... |
Arguments passed to an |
term_labels |
Optional named vector used to relabel displayed terms. Names should match values in the term column and values are the labels to display. |
sort_terms |
How to sort rows: |
exponentiate |
Compatibility argument. |
p_method |
Subgroup p-value placement. |
term |
Column name holding the model term identifier. |
estimate |
Column name holding the point estimate. |
conf.low |
Column name holding the lower confidence bound. |
conf.high |
Column name holding the upper confidence bound. |
label |
Optional column name used for the displayed row label. |
group |
Optional column name used for color-grouping multiple estimates per row. If this column is a factor, its levels control the group legend and vertical dodge order. |
grouping |
Optional column name used to split rows into grouped plot sections. |
separate_groups |
Optional column name used to identify labeled variable blocks that can be outlined with separator lines. |
n |
Optional column name holding sample sizes or other N labels for table helpers. |
events |
Optional column name holding event counts or event labels for table helpers. |
p.value |
Optional column name holding p-values. |
estimate_scale |
Semantic scale of the stored estimates. One of
|
axis_transform |
Transformation used for the plotting axis. Defaults
to |
effect_label |
Short label for the effect measure, such as |
conf.level |
Confidence level represented by the interval columns, or
|
reference_value |
Numeric null/reference value, or |
source_model |
Optional character vector identifying the source model class. The complete fitted model is not retained. |
source_package |
Optional package name identifying the model source. |
subgroup |
For data frames, an optional column name defining
presentation-only hierarchical subgroup blocks. Missing or empty values
identify ordinary standalone estimates. Rows with the same non-empty
value must form one contiguous block within each facet. When |
row_type |
Optional column name defining semantic rows: |
conf.int |
Logical; model methods require |
intercept |
Logical; for model methods, whether to retain the intercept term. |
focal |
For fitted-model methods, the predictor whose conditional effect is estimated within each subgroup level. It may be continuous or a factor. Factor effects compare each non-reference level with the first level. Ignored for data-frame methods. |
A forest_data data-frame subclass ready for ggforestplot() and
the table composition helpers. Original data-frame columns are retained
for table helpers so they can be displayed with
add_forest_table(columns = ...).
raw <- data.frame( variable = c("Age", "BMI", "Treatment"), beta = c(0.10, -0.08, 0.34), lower = c(0.02, -0.16, 0.12), upper = c(0.18, 0.00, 0.56) ) as_forest_data( data = raw, term = "variable", estimate = "beta", conf.low = "lower", conf.high = "upper" )raw <- data.frame( variable = c("Age", "BMI", "Treatment"), beta = c(0.10, -0.08, 0.34), lower = c(0.02, -0.16, 0.12), upper = c(0.18, 0.00, 0.56) ) as_forest_data( data = raw, term = "variable", estimate = "beta", conf.low = "lower", conf.high = "upper" )
Tidies multiple fitted models and stacks their fixed-effect coefficient
tables into a single forest-plot data frame. The resulting data can be
passed directly to ggforestplot(), where model labels are used as the
grouping variable for dodged, color-coded estimates.
bind_forest_models(models, model_labels = NULL, exponentiate = NULL, ...)bind_forest_models(models, model_labels = NULL, exponentiate = NULL, ...)
models |
A non-empty list of fitted model objects supported by an
|
model_labels |
Optional labels used to identify each model in the
forest plot. Defaults to list names when present, otherwise |
exponentiate |
|
... |
Additional arguments passed to |
A standardized forest-plot data frame with one row per model term
and a group column containing the model labels.
if (requireNamespace("broom", quietly = TRUE)) { fit1 <- lm(mpg ~ wt + hp, data = mtcars) fit2 <- lm(mpg ~ wt + qsec, data = mtcars) bound <- bind_forest_models( list(Base = fit1, Adjusted = fit2) ) ggforestplot(bound) }if (requireNamespace("broom", quietly = TRUE)) { fit1 <- lm(mpg ~ wt + hp, data = mtcars) fit2 <- lm(mpg ~ wt + qsec, data = mtcars) bound <- bind_forest_models( list(Base = fit1, Adjusted = fit2) ) ggforestplot(bound) }
Returns the semantic and provenance metadata attached to a forest_data
object. Plotting behavior is determined by this metadata rather than by the
class of the original fitted model.
forest_metadata(x)forest_metadata(x)
x |
A |
A named metadata list, including the effect scale, reference value,
source mappings, and subgroup p_method display contract.
Builds a forest plot from standardized coefficient data or directly from a fitted model.
ggforestplot( data, term = "term", estimate = "estimate", conf.low = "conf.low", conf.high = "conf.high", label = term, term_labels = NULL, group = NULL, facet = NULL, facet_strip_position = c("left", "right"), separate_groups = NULL, n = NULL, events = NULL, p.value = NULL, exponentiate = NULL, conf.level = 0.95, sort_terms = c("none", "descending", "ascending"), point_size = 2.3, point_shape = 19, linewidth = 0.5, line_size = NULL, staple_width = 0.2, ci_limits = NULL, ci_arrows = TRUE, ci_arrow_length = 0.08, ci_arrow_type = c("closed", "open"), dodge_width = 0.6, separate_lines = FALSE, separator_line_linetype = 2, separator_line_colour = "black", separator_line_size = 0.4, striped_rows = FALSE, stripe_fill = "grey95", stripe_colour = NA, stripe_alpha = 1, ref_line = NULL, ref_label = NULL, ref_linetype = 2, ref_color = "grey60", subgroup = NULL, p_method = c("overall", "level"), row_type = NULL )ggforestplot( data, term = "term", estimate = "estimate", conf.low = "conf.low", conf.high = "conf.high", label = term, term_labels = NULL, group = NULL, facet = NULL, facet_strip_position = c("left", "right"), separate_groups = NULL, n = NULL, events = NULL, p.value = NULL, exponentiate = NULL, conf.level = 0.95, sort_terms = c("none", "descending", "ascending"), point_size = 2.3, point_shape = 19, linewidth = 0.5, line_size = NULL, staple_width = 0.2, ci_limits = NULL, ci_arrows = TRUE, ci_arrow_length = 0.08, ci_arrow_type = c("closed", "open"), dodge_width = 0.6, separate_lines = FALSE, separator_line_linetype = 2, separator_line_colour = "black", separator_line_size = 0.4, striped_rows = FALSE, stripe_fill = "grey95", stripe_colour = NA, stripe_alpha = 1, ref_line = NULL, ref_label = NULL, ref_linetype = 2, ref_color = "grey60", subgroup = NULL, p_method = c("overall", "level"), row_type = NULL )
data |
Either a tidy coefficient data frame or a model object
supported by |
term |
Column name holding the model term identifiers. |
estimate |
Column name holding the point estimates. |
conf.low |
Column name holding the lower confidence bounds. |
conf.high |
Column name holding the upper confidence bounds. |
label |
Optional column name used for the displayed row labels. |
term_labels |
Optional named vector used to relabel displayed terms. Names should match values in the term column and values are the labels to display. |
group |
Optional column name used for color-grouping estimates. If this column is a factor, its levels control the group legend and vertical dodge order. |
facet |
Optional column name used to split rows into faceted plot sections. If this column is a factor, its levels control facet order. |
facet_strip_position |
Positioning for facet strip labels. |
separate_groups |
Optional column name used to identify labeled variable blocks that can be outlined with grid lines. |
n |
Optional column name holding sample sizes or other N labels for table helpers. |
events |
Optional column name holding event counts or event labels for table helpers. |
p.value |
Optional column name holding p-values. |
exponentiate |
Logical; if |
conf.level |
Confidence level represented by model or data-frame
interval columns. Defaults to |
sort_terms |
How to sort rows: |
point_size |
Point size for coefficient markers. |
point_shape |
Shape used for coefficient markers. |
linewidth |
Line width for confidence intervals. |
line_size |
Deprecated. Use |
staple_width |
Width of the terminal staples on confidence interval lines. |
ci_limits |
Optional numeric vector of length 2 used to truncate
displayed confidence intervals. Intervals extending beyond these limits
are clipped to the boundary and marked with arrows when |
ci_arrows |
Logical; if |
ci_arrow_length |
Length of CI truncation arrows in inches. |
ci_arrow_type |
Arrowhead type for truncated confidence intervals.
Passed to |
dodge_width |
Horizontal dodging used for grouped estimates. |
separate_lines |
Logical; if |
separator_line_linetype |
Line type used for separator lines. |
separator_line_colour |
Colour used for separator lines. |
separator_line_size |
Line width used for separator lines. |
striped_rows |
Logical; if |
stripe_fill |
Fill color used for shaded rows. |
stripe_colour |
Border color for shaded rows. |
stripe_alpha |
Transparency for shaded rows. |
ref_line |
Numeric x-value where the reference line is drawn, or
|
ref_label |
Optional label drawn alongside the reference line. |
ref_linetype |
Line type for the reference line. |
ref_color |
Color for the reference line. |
subgroup |
Optional column name defining hierarchical subgroup blocks.
Missing or empty values identify ordinary standalone estimates. Each
non-empty subgroup must form one contiguous block within a facet. This is
a presentation-only mapping; subgroups and contrasts are not inferred.
With the default |
p_method |
Subgroup p-value placement for data-frame input.
|
row_type |
Optional data-frame column mapping for semantic row types.
|
A ggplot object. Use standard ggplot2 functions such as
ggplot2::labs() for plot labels, and add composition helpers after
styling the main plot.
coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.10, -0.08, 0.34), conf.low = c(0.02, -0.16, 0.12), conf.high = c(0.18, 0.00, 0.56) ) ggforestplot(coefs) ggforestplot(coefs, striped_rows = TRUE, point_shape = 17)coefs <- data.frame( term = c("Age", "BMI", "Treatment"), estimate = c(0.10, -0.08, 0.34), conf.low = c(0.02, -0.16, 0.12), conf.high = c(0.18, 0.00, 0.56) ) ggforestplot(coefs) ggforestplot(coefs, striped_rows = TRUE, point_shape = 17)
Uses broom::tidy() to convert a fitted model into forest-plot data. When
subgroup effects are requested, marginaleffects::avg_slopes() or
marginaleffects::avg_comparisons() derives conditional average effects
from the original fitted model and its covariance matrix. Mixed models are
supported through broom.mixed tidy methods when that package is installed.
tidy_forest_model( model, conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") )tidy_forest_model( model, conf.int = TRUE, conf.level = 0.95, exponentiate = NULL, intercept = FALSE, term_labels = NULL, sort_terms = c("none", "descending", "ascending"), subgroup = NULL, focal = NULL, p_method = c("overall", "level") )
model |
A fitted model object supported by |
conf.int |
Logical; if |
conf.level |
Confidence level for intervals. |
exponentiate |
|
intercept |
Logical; if |
term_labels |
Optional named vector used to relabel displayed terms. Names should match model term names and values are the labels to display. |
sort_terms |
How to sort rows: |
subgroup |
|
focal |
Optional predictor whose conditional effect is estimated within each subgroup level. It may be continuous or a factor. For factors, each non-reference level is contrasted with the first factor level. |
p_method |
Subgroup p-value method. |
With subgroup = NULL, the function retains its ordinary coefficient-tidy
behavior. When subgroup effects are requested, interaction selection uses
the fitted model's terms and model frame rather than parsing coefficient
names. The selected focal main effect, subgroup main-effect coefficients,
and raw interaction coefficients are replaced at their original position by
one hierarchical subgroup block. Unrelated coefficient rows stay in formula
order.
Continuous focal predictors use
marginaleffects::avg_slopes() within each observed subgroup. Factor focal
predictors use marginaleffects::avg_comparisons() and compare each
non-reference level with the first factor level. Both functions use the
original fitted model and its variance-covariance matrix; no subgroup models
are refitted.
Automatic selection is deliberately conservative. It accepts one
unambiguous continuous-by-factor interaction. Factor-by-factor interactions
require explicit focal and subgroup names. Continuous subgroups,
transformed focal terms, multiple interactions involving the selected
predictors, and three-way interactions are rejected.
Linear and identity-link effects remain additive. Logit and log-link effects
are estimated on the link scale and use the existing exponentiate
semantics to return odds ratios or ratios by default. Cox effects are
estimated on the linear-predictor scale and returned as hazard ratios by
default. Other links fail rather than silently returning a response-scale
estimand with a different interpretation.
The canonical p.value column always contains both ordinary-covariate and
interaction-related tests. With p_method = "overall", subgroup rows store
an omnibus Wald test of the selected interaction, which the display layer
promotes to the parent header. With p_method = "level", subgroup rows
retain the post-estimation p-value for each slope or comparison and display
it alongside that estimate.
A forest_data object ready for ggforestplot(). Derived rows add
subgroup_level, focal, model_term, contrast, estimand,
and effect_scale columns. Their canonical p.value follows p_method
and shares one table column with ordinary covariate p-values.
if (requireNamespace("broom", quietly = TRUE)) { fit <- lm(mpg ~ wt + hp + qsec, data = mtcars) tidy_forest_model(fit) if (requireNamespace("marginaleffects", quietly = TRUE)) { interaction_fit <- lm(wt ~ mpg * factor(cyl), data = mtcars) tidy_forest_model( interaction_fit, subgroup = "auto", focal = "mpg" ) } set.seed(123) logit_data <- data.frame( age = rnorm(250, mean = 62, sd = 8), bmi = rnorm(250, mean = 28, sd = 4), treatment = factor(rbinom(250, 1, 0.45), labels = c("Control", "Treatment")) ) linpred <- -9 + 0.09 * logit_data$age + 0.11 * logit_data$bmi + 0.9 * (logit_data$treatment == "Treatment") logit_data$event <- rbinom(250, 1, plogis(linpred)) logit_fit <- glm(event ~ age + bmi + treatment, data = logit_data, family = binomial()) tidy_forest_model(logit_fit, exponentiate = TRUE) }if (requireNamespace("broom", quietly = TRUE)) { fit <- lm(mpg ~ wt + hp + qsec, data = mtcars) tidy_forest_model(fit) if (requireNamespace("marginaleffects", quietly = TRUE)) { interaction_fit <- lm(wt ~ mpg * factor(cyl), data = mtcars) tidy_forest_model( interaction_fit, subgroup = "auto", focal = "mpg" ) } set.seed(123) logit_data <- data.frame( age = rnorm(250, mean = 62, sd = 8), bmi = rnorm(250, mean = 28, sd = 4), treatment = factor(rbinom(250, 1, 0.45), labels = c("Control", "Treatment")) ) linpred <- -9 + 0.09 * logit_data$age + 0.11 * logit_data$bmi + 0.9 * (logit_data$treatment == "Treatment") logit_data$event <- rbinom(250, 1, plogis(linpred)) logit_fit <- glm(event ~ age + bmi + treatment, data = logit_data, family = binomial()) tidy_forest_model(logit_fit, exponentiate = TRUE) }