Correctly place geom_text labels in forest plot with "fill" parameter in ggplot2

Hi There,

I want to create annotated publication-ready forest plots comparing different models. How do I ensure that the labels are placed above and tight against the corresponding error bars and do not overlap?

Thank you for your help!

Here is what I tried:

library(tidyverse)
#> Warning: package 'tibble' was built under R version 4.1.2
#> Warning: package 'tidyr' was built under R version 4.1.2
#> Warning: package 'readr' was built under R version 4.1.2
#> Warning: package 'dplyr' was built under R version 4.1.2
library(knitr)
#> Warning: package 'knitr' was built under R version 4.1.2
data <- tibble::tribble(
  ~term, ~n_obs,   ~estimate,   ~conf.low,  ~conf.high,            ~ci,    ~p.value,  ~group,
    "A",   101L,        0.62, 0.497390282, 0.797429694, "0.50 to 0.80", 0.000123131,   "One",
    "A",    65L,        0.57, 0.468908017, 0.693458768, "0.47 to 0.69", 1.83138e-08,   "Two",
    "A",    36L,        0.81, 0.623804568, 1.064787867, "0.62 to 1.06", 0.133680272, "Three",
    "B",    26L,        0.87, 0.665400224,   1.1489204, "0.67 to 1.15", 0.335220534,   "One",
    "B",    16L,        1.02, 0.755403541, 1.388386542, "0.76 to 1.39", 0.878076678,   "Two",
    "B",    10L,        0.29, 0.091804704, 0.978289216, "0.09 to 0.98", 0.045898245, "Three",
    "C",   143L,        0.90, 0.749027775, 1.089930323, "0.75 to 1.09", 0.289131987,   "One",
    "C",    82L,        1.02,  0.82229374, 1.286815562, "0.82 to 1.29", 0.804649191,   "Two",
    "C",    61L,        0.61, 0.359730119, 1.036462037, "0.36 to 1.04",  0.06765433, "Three"
  )
data %>% kable()
term n_obs estimate conf.low conf.high ci p.value group
A 101 0.62 0.4973903 0.7974297 0.50 to 0.80 0.0001231 One
A 65 0.57 0.4689080 0.6934588 0.47 to 0.69 0.0000000 Two
A 36 0.81 0.6238046 1.0647879 0.62 to 1.06 0.1336803 Three
B 26 0.87 0.6654002 1.1489204 0.67 to 1.15 0.3352205 One
B 16 1.02 0.7554035 1.3883865 0.76 to 1.39 0.8780767 Two
B 10 0.29 0.0918047 0.9782892 0.09 to 0.98 0.0458982 Three
C 143 0.90 0.7490278 1.0899303 0.75 to 1.09 0.2891320 One
C 82 1.02 0.8222937 1.2868156 0.82 to 1.29 0.8046492 Two
C 61 0.61 0.3597301 1.0364620 0.36 to 1.04 0.0676543 Three
data %>% rowwise() %>%
  ## plot with variable on the y axis and estimate (OR) on the x axis
  ggplot(aes(x = estimate, y = term, color = group), alpha = .7, width = .7) +

  ## show the estimate as a point
  geom_point(position = position_dodge(.9), size = 1.5) +
        
  ## add in labels     
  geom_text(aes(color = "black", label = paste0(estimate, " (", ci, ") n = ", n_obs)), position = position_dodge(1.9), show.legend = FALSE, check_overlap = FALSE) +

  ## add in an error bar for the confidence intervals
  geom_errorbar(aes(xmin = conf.low, xmax = conf.high), position = position_dodge(.9), size = 1) +
  ggplot2::theme_bw() +
  scale_colour_grey() +

  ## show where OR = 1 is for reference as a dashed line
  geom_vline(xintercept = 1, linetype = "dashed") +
  ylab("") +
  xlab("") +
  theme(legend.position = "top")
#> Warning: position_dodge requires non-overlapping x intervals

Created on 2022-03-09 by the reprex package (v2.0.1)

1 Like

I've also asked for help on stackoverflow too. I'll post an update here once I get a solution.

Here is a link to the solution.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.