Search code examples
rggplot2r-forestplot

How to add OR and 95% CI as text outside a forest plot?


I have previously asked a similar question, which was "how to add OR and CI 95% as text into a forest plot". In that previous question, I got my codes from a third question by someone named stupidwolf. I used his codes to get a forest plot, BUT without OR and CI as text. This is the codes I used from stupidwolf, which worked for me.

library('ggplot2') 

Outcome_order <- c('Outcome C', 'Outcome A', 'Outcome B', 'Outcome D')

#this is the first dataset you have
df1 <- data.frame(Outcome=c("Outcome A", "Outcome B", "Outcome C", "Outcome D"),
   OR=c(1.50, 2.60, 1.70, 1.30),
   Lower=c(1.00, 0.98, 0.60, 1.20),
   Upper=c(2.00, 3.01, 1.80, 2.20))
# add a group column
df1$group <- "X"
# create a second dataset, similar format to first
df2 <- df1
# different group
df2$group <- "Y"
# and we adjust the values a bit, so it will look different in the plot
df2[,c("OR","Lower","Upper")] <- df2[,c("OR","Lower","Upper")] +0.5

# combine the two datasets                      
df = rbind(df1,df2)
# you can do the factoring here
df$Outcome = factor (df$Outcome, level=Outcome_order)

#define colours for dots and bars
dotCOLS = c("#a6d8f0","#f9b282")
barCOLS = c("#008fd5","#de6b35")


p <- ggplot(df, aes(x=Outcome, y=OR, ymin=Lower, ymax=Upper,col=group,fill=group)) + 
#specify position here
  geom_linerange(size=5,position=position_dodge(width = 0.5)) +
  geom_hline(yintercept=1, lty=2) +
#specify position here too
  geom_point(size=3, shape=21, colour="white", stroke = 0.5,position=position_dodge(width = 0.5)) +
  scale_fill_manual(values=barCOLS)+
  scale_color_manual(values=dotCOLS)+
  scale_x_discrete(name="(Post)operative outcomes") +
  scale_y_continuous(name="Odds ratio", limits = c(0.5, 5)) +
  coord_flip() +
  theme_minimal()

Then I asked in my previous question, if someone could help me with adding the OR and CI as text on the forest plot, which Allan Cameron helped me with. This almost solved my problem.

So what I did was this, as he suggested me to do and it worked for me as well:

ggplot(df, aes(x = Outcome, y = OR, ymin = Lower, ymax = Upper,
               col = group, fill = group)) + 
  geom_linerange(linewidth = 5, position = position_dodge(width = 0.5)) +
  geom_hline(yintercept = 1, lty = 2) +
  geom_point(size = 3, shape = 21, colour = "white", stroke = 0.5,
             position = position_dodge(width = 0.5)) +
  geom_text(aes(y = 3.75, group = group, 
                label = paste0("OR ", round(OR, 2), ", (", round(Lower, 2), 
                               " - ", round(Upper, 2), ")")), hjust = 0,
            position = position_dodge(width = 0.5), color = "black") +
  scale_fill_manual(values = barCOLS) +
  scale_color_manual(values = dotCOLS) +
  scale_x_discrete(name = "(Post)operative outcomes") +
  scale_y_continuous(name = "Odds ratio", limits = c(0.5, 5)) +
  coord_flip() +
  theme_minimal()

And I get this forest plot

enter image description here

As you can see on the forest plot the OR and CI text is inside the plot area. So I have following questions that I hope someone can help me to fix:

  1. How to add one title "OR" above all the OR values instead of it is written for each OR value?

  2. How can I plot the OR and CI text outside the plot, like on the side to the right. Because on my real plot I have very long CI unfortunately, so I can't avoid the text merging with the horizontal CI lines. If I start moving the OR text by changing the y = 3.75 position more to the right, then the OR and 95%CI text starts to disappear (half of it), because it gets pushed out of the plot. So I was thinking if I could plot it outside the plot, then it will solve the issue maybe? But how?

This is the link to my previous question if necessary: How to add OR and 95% CI as text into a forest plot?


Solution

  • Using the patchwork package.

    library(ggplot2)
    library(patchwork)
    
    p1 <- ggplot(df, aes(x = Outcome, y = OR, ymin = Lower, ymax = Upper,
                   col = group, fill = group)) + 
        geom_linerange(size = 5, position = position_dodge(width = 0.5)) +
        geom_hline(yintercept = 1, lty = 2) +
        geom_point(size = 3, shape = 21, colour = "white", stroke = 0.5,
                   position = position_dodge(width = 0.5)) +
        scale_fill_manual(values = barCOLS) +
        scale_color_manual(values = dotCOLS) +
        scale_x_discrete(name = "(Post)operative outcomes") +
        scale_y_continuous(name = "Odds ratio", limits = c(0.5, 5)) +
        coord_flip() +
        theme_minimal()
    
    
    p2 <- ggplot(df, aes(x = Outcome, y = 1.25, ymin = Lower, ymax = Upper)) + 
        geom_text(aes(group = group, 
                      label = paste0(round(OR, 2), ", (", round(Lower, 2), 
                                     " - ", round(Upper, 2), ")")),
                  position = position_dodge(width = 0.5), color = "black") +
        labs(title  = "OR") +
        coord_flip() +
        theme_void()
    
    
    p1 + p2 
    
    

    enter image description here