2

I'd like to make a forest plot for my project. Since it is not a typical forest plot built-in any R package, I found the first figure of this page is helpful to my goal, a side table accompanied with the forest plot: https://mcfromnz.wordpress.com/2012/11/06/forest-plots-in-r-ggplot-with-side-table/
The code which produces that particular figure is pasted below (the original link:https://github.com/nzcoops/blog_code/blob/master/forest_plot.Rmd)

The problem that I ran into is in the "data_table" step. An error pop up when I type the following in R:

data_table

Error: Aesthetics must be either length 1 or the same as the data (28): yintercept

I guess the issue came from geom_hlinein data_table. After some online search and some try-and-error, I still cannot get rid of that error message and wonder if I can get some help here. Thanks in advance for your help.

--Code that particular produce the first figure:

library(ggplot2)
library(gridExtra)
dat <- data.frame(group = factor(c("A","B","C","D","E","F","G"), levels=c("F","E","D","C","B","A","G")),
              cen = c(3.1,2.0,1.6,3.2,3.6,7.6,NA),
              low = c(2,0.9,0.8,1.5,2,4.2,NA),
              high = c(6,4,2,6,5,14.5,NA))
theme_set(theme_bw())
theme_update(
axis.line = element_line(colour = "black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.margin = unit(c(0,0,0,0), "lines"))

p <- ggplot(dat,aes(cen,group)) + 
geom_point(size=5, shape=18) +
geom_errorbarh(aes(xmax = high, xmin = low), height = 0.15) +
geom_vline(xintercept = 1, linetype = "longdash") +
scale_x_continuous(breaks = seq(0,14,1), labels = seq(0,14,1)) +
labs(x="Adjusted Odds Ratio", y="")
data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
geom_hline(aes(yintercept=c(6.5,7.5))) + 
theme(panel.grid.major = element_blank(), 
      legend.position = "none",
      panel.border = element_blank(), 
      axis.text.x = element_text(colour="white"),#element_blank(),
      axis.text.y = element_blank(), 
      axis.ticks = element_line(colour="white"),#element_blank(),
      plot.margin = unit(c(0,0,0,0), "lines")) +
          labs(x="",y="") +
          coord_cartesian(xlim=c(1,4.5))

lab <- data.frame(V0 = factor(c("A","B","C","D","E","F","G","A","B","C","D","E","F","G","A","B","C","D","E","F","G","A","B","C","D","E","F","G"),, levels=c("G","F","E","D","C","B","A")),
              V05 = rep(c(1,2,3,4),each=7),
              V1 = c("Occuption","Active","","Inactive","","Inactive","","Recreation","Inactive","","Active","","Inactive","","Gender","Men","Women","Men","Women","Men","Women","OR",3.1,2.0,1.6,3.2,3.6,7.6))

data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
geom_hline(aes(yintercept=c(6.5,7.5))) + 
theme(panel.grid.major = element_blank(), 
      legend.position = "none",
      panel.border = element_blank(), 
      axis.text.x = element_text(colour="white"),#element_blank(),
      axis.text.y = element_blank(), 
      axis.ticks = element_line(colour="white"),#element_blank(),
      plot.margin = unit(c(0,0,0,0), "lines")) +
          labs(x="",y="") +
          coord_cartesian(xlim=c(1,4.5))
Liz Sugar
  • 123
  • 3

2 Answers2

0

The easiest fix would be separating geom_hline into 2 different calls

data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
  geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
  geom_hline(aes(yintercept=c(6.5))) +
  geom_hline(aes(yintercept=c(7.5))) +
  theme(panel.grid.major = element_blank(), 
        legend.position = "none",
        panel.border = element_blank(), 
        axis.text.x = element_text(colour="white"),#element_blank(),
        axis.text.y = element_blank(), 
        axis.ticks = element_line(colour="white"),#element_blank(),
        plot.margin = unit(c(0,0,0,0), "lines")) +
  labs(x="",y="") +
  coord_cartesian(xlim=c(1,4.5))  
data_table  

Created on 2018-03-31 by the reprex package (v0.2.0).

Tung
  • 26,371
  • 7
  • 91
  • 115
  • 1
    WOW! departing geom_hline is like a MAGIC!! Thank you so much!! Why separating geom_hline matters in this case? – Liz Sugar Mar 31 '18 at 19:50
  • When you use `aes`, you can map `color`, `fill`, `shape`, `size`, etc. based on variables in your data frame and also create legend for them. If you don't want any of that, use the one suggested by @Gregor – Tung Apr 01 '18 at 05:24
  • In your case, when you put `yintercept` inside `aes`, ggplot expected the supplied vector had the same length (row) as your data frame. You can try `lab$line1 <- 6.5` and `geom_hline(aes(yintercept=line))` – Tung Apr 01 '18 at 05:33
  • Bonus: to align multiple plots in R, there are some other choices from `grid.arrange` https://stackoverflow.com/a/47668467/786542 – Tung Apr 01 '18 at 05:36
  • Bonus 2: example of using `ase` & `geom_hline` https://stackoverflow.com/a/49453699/786542 – Tung Apr 01 '18 at 05:50
0

You don't need to use aes() with geom_hline (only use aes() if you want a horizontal line for every row of your data.) You can just do:

geom_hline(yintercept = c(6.5, 7.5))

This is explained in the help, see ?geom_hline for more details.

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • Yay! it also works!! Thanks a lot!! I tried to delete the whole geom_hline and it doesn't work. Now I know I have to keep aes() there. Seems like aes() is a mandatory element in ggplot? – Liz Sugar Mar 31 '18 at 19:33