The goal of forester is to make it easy for you to create a publication-quality forest plot with as much or as little information displayed on either side as you require.
This package is currently early in development, and must be installed from this github repo.
devtools::install_github("rdboyes/forester")
Suppose we wish to replicate the following figure published in the NEJM [1]:
forester simply requires the left side of the table (in this case, three columns with Subgroups and counts for each of two groups) and vectors which contain the point estimates and confidence intervals.
library(forester)
table <- readxl::read_excel(here::here("inst/extdata/example_figure_data.xlsx"))
# indent the subgroup if there is a number in the placebo column
table$Subgroup <- ifelse(is.na(table$Placebo),
table$Subgroup,
paste0(" ", table$Subgroup))
# remove indent of the first row
table$Subgroup[1] <- "All Patients"
# use forester to create the table with forest plot
forester(left_side_data = table[,1:3],
estimate = table$Estimate,
ci_low = table$`CI low`,
ci_high = table$`CI high`,
display = FALSE,
xlim = c(-100, 25),
file_path = here::here("man/figures/forester_plot.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 8 rows containing missing values (geom_point).
#> Warning: Removed 8 rows containing missing values (geom_errorbarh).
forester handles the alignment of the graph and the table automatically, so figures with fewer rows or columns should work by simply passing a smaller data frame to the function:
forester(left_side_data = table[1:12,1:3],
estimate = table$Estimate[1:12],
ci_low = table$`CI low`[1:12],
ci_high = table$`CI high`[1:12],
display = FALSE,
file_path = here::here("man/figures/fewer_rows.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 3 rows containing missing values (geom_point).
#> Warning: Removed 3 rows containing missing values (geom_errorbarh).
forester(left_side_data = table[,1],
estimate = table$Estimate,
ci_low = table$`CI low`,
ci_high = table$`CI high`,
display = FALSE,
file_path = here::here("man/figures/fewer_cols.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 8 rows containing missing values (geom_point).
#> Warning: Removed 8 rows containing missing values (geom_errorbarh).
While Courier has a certain appeal, you might want to give your tables a more modern look. However, due to the difficulty of aligning all elements when using them, the use of non-monospaced fonts should be considered experimental at this stage.
library(extrafont)
#> Registering fonts with R
loadfonts(device = "win")
windowsFonts("Fira Sans" = windowsFont("Fira Sans"))
forester(left_side_data = table[,1:3],
estimate = table$Estimate,
ci_low = table$`CI low`,
ci_high = table$`CI high`,
display = FALSE,
file_path = here::here("man/figures/forester_plot_fira.png"),
font_family = "Fira Sans")
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 8 rows containing missing values (geom_point).
#> Warning: Removed 8 rows containing missing values (geom_errorbarh).
Adjusting table properties with different fonts will still work:
forester(left_side_data = table[1:12,1:3],
estimate = table$Estimate[1:12],
ci_low = table$`CI low`[1:12],
ci_high = table$`CI high`[1:12],
display = FALSE,
font_family = "Fira Sans",
file_path = here::here("man/figures/fewer_rows_fira.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 3 rows containing missing values (geom_point).
#> Warning: Removed 3 rows containing missing values (geom_errorbarh).
windowsFonts("Times New Roman" = windowsFont("Times New Roman"))
forester(left_side_data = table[1:12,1:3],
estimate = table$Estimate[1:12],
ci_low = table$`CI low`[1:12],
ci_high = table$`CI high`[1:12],
display = FALSE,
font_family = "Times New Roman",
file_path = here::here("man/figures/fewer_rows_times.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 3 rows containing missing values (geom_point).
#> Warning: Removed 3 rows containing missing values (geom_errorbarh).
forester(left_side_data = table[,1:3],
estimate = table$Estimate,
ci_low = table$`CI low`,
ci_high = table$`CI high`,
display = FALSE,
file_path = here::here("man/figures/forester_plot_arrows.png"),
font_family = "Fira Sans",
xlim = c(-100, 25),
xbreaks = c(-100, -75, -50, -25, 0, 25),
arrows = TRUE,
arrow_labels = c("Inclisiran Better", "Placebo Better"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 8 rows containing missing values (geom_point).
#> Warning: Removed 8 rows containing missing values (geom_errorbarh).
Custom ggplot objects can be passed to the forester
function using the
parameter add_plot
. To align the plot with the rows of the table, the
vertical center of the bottom row is at y = 0, and each row is one unit
tall on the y axis. add_plot_width
can be set to customize the width
of the plot (units are relative to the width of the table).
library(ggplot2)
library(tibble)
ex_plot <- ggplot(tibble(x = rep(1:7, each = 15), y = rep(0:14, times = 7)), aes(x = x, y = y)) +
geom_point()
forester(left_side_data = table[1:15,1:3],
estimate = table$Estimate[1:15],
ci_low = table$`CI low`[1:15],
ci_high = table$`CI high`[1:15],
display = FALSE,
font_family = "Times New Roman",
add_plot = ex_plot,
file_path = here::here("man/figures/add_dots.png"))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.
#> Warning: Removed 4 rows containing missing values (geom_point).
#> Warning: Removed 4 rows containing missing values (geom_errorbarh).
- Ray, K. K., Wright, R. S., Kallend, D., Koenig, W., Leiter, L. A., Raal, F. J., Bisch, J. A., Richardson, T., Jaros, M., Wijngaard, P. L. J., Kastelein, J. J. P., & ORION-10 and ORION-11 Investigators. (2020). Two Phase 3 Trials of Inclisiran in Patients with Elevated LDL Cholesterol. The New England Journal of Medicine, 382(16), 1507–1519.