Search code examples
rggplot2facet

ggplot2:: Facetting plot with the same reference plot in all panels


I would like to facet a plot, but with a reference plot in each panel. Let me try to show with pictures what I want to achieve: My example data_frame:

require(dplyr)

df <- data_frame( id = c(rep('ctr',40), rep('pat',80)),
                  class = c(rep('ctr',40), rep(c('a','b'), each = 40)),
                  rank =  rep (1:20,6),
                  mean = c(rep(seq(3,-3, length.out = 20),2), 
                           rep(seq(1,-4, length.out = 20),2), 
                           rep(seq(-2,-8, length.out = 20),2)),
                  sd = rep(seq(1.2,0.8, length.out = 20), times = 6),
                  exam = rep(c('blue','red'), each = 20, times = 3))

My plot:

# first, create reference plot of the 'controls'
require(ggplot2)
p_ctr <- ggplot() + 
 geom_line(data = filter(df, id == 'ctr'),
            aes(x=rank, y=mean, color=exam), linetype=1) + 
  geom_ribbon(data = filter(df, id == 'ctr'),
              aes(x = rank, ymax = mean+sd, ymin = mean-sd, 
                  fill = exam), alpha = .1) +
  scale_colour_manual(values = c("#00b6eb","#eb0041")) + 
  scale_fill_manual(values = c("#00b6eb","#eb0041")) 

# then, overlay with plot of 'patients'

p_ctr + geom_line(data = filter(df, id == 'pat'), 
              aes(x=rank, y=mean, linetype = class)) +
  geom_ribbon(data = filter(df, id == 'pat'), 
              aes(x = rank, ymax = mean+sd, ymin = mean-sd,
                  group = class), 
              alpha = .1) +
  facet_wrap(~exam)

That is halfway there: enter image description here Ideally, however, I would like to plot the different "classes" in separate panels, but with the control plot as a reference in each panel:

Expected result: **Expected result**

I have tried different combinations of facetting, without good result. I guess, there must be a simple solution?


Solution

  • Maybe like so.

    library(dplyr)
    library(ggplot2)
    
    df1 <- filter(df, id == 'ctr')
    df2 <- filter(df, id == 'pat')
    df2 <- dplyr::rename(df2, class_2 = class)
    
    p_ctr <- ggplot() + 
     geom_line(data = df1, aes(x=rank, y=mean, color=exam)) +
     geom_ribbon(data = df1,
                 aes(x = rank, ymax = mean+sd, ymin = mean-sd, fill = exam),
                 alpha = .1) +
     scale_colour_manual(values = c("#00b6eb","#eb0041")) +
     scale_fill_manual(values = c("#00b6eb","#eb0041")) +
     geom_line(data = df2,
               aes(x=rank, y=mean)) +
     geom_ribbon(data = df2,
                 aes(x = rank, ymax = mean+sd, ymin = mean-sd),
                 alpha = .1) +
     facet_grid(class_2 ~ exam)
    
    p_ctr
    

    enter image description here

    Using facet_wrap gives me the following error:

    error in gList(list(x = 0.5, y = 0.5, width = 1, height = 1, just = "centre", : only 'grobs' allowed in "gList"


    You probably came across this plot while looking for the solution.

    p_ctr + geom_line(data = filter(df, id == 'pat'), 
                      aes(x=rank, y=mean)) +
            geom_ribbon(data = filter(df, id == 'pat'), 
                        aes(x = rank, ymax = mean+sd, ymin = mean-sd), 
                        alpha = .1) +
          # facet_wrap(~exam) +
            facet_grid(class ~ exam)
    

    enter image description here

    This is basically your reference plot and its overlay, without the linetype and group arguments. Additionally I faceted by class ~ exam. From this plot you see that 'the problem' is that class contains three unique elements: a, b and ctr. That's why I renamed the variable class in df2 to be class_2 which has only two unique elements: a and b. Faceting by class_2 ~ exam then gives the desired output.

    I hope this helps.