rggplot2r-gridgrob

changing legend of faceted boxplot in ggplot2 to have groups with similar names inside


This question builds off of enter link description here but is in the context of faceted boxplots.

So, I have the following code:

set.seed(20210714)
dd <- data.frame(Method = rep(c("A", "B", "C"), each = 60), Pattern = rep(c("X", "Y", "Z"), times = 30), X1 = runif(180), Complexity = rep(c("High", "Low"), times = 90), nsim = rep(rep(1:10, times = 9), each = 2), n = 10)
dd1 <-  data.frame(Method = rep(c("A", "B", "C"), each = 60), Pattern = rep(c("X", "Y", "Z"), times = 30), X1 = runif(180), Complexity = rep(c("High", "Low"), times = 90), nsim = rep(rep(1:10, times = 9), each = 2), n = 5)
dd <- rbind(dd, dd1)


library(ggplot2)

# create dummy dataframe.
dummy.df <- dd
dummy.df[nrow(dd) + 1:2,"Pattern"] <- unique(dd$Pattern)[-3]
dummy.df[nrow(dd) + 1:2,"Method"] <- "ZZZ"
dummy.df[nrow(dd) + 1:2,"Complexity"] <- c("High","Low")

dummy.df$dummy <- interaction(dummy.df$Method,dummy.df$Pattern)             

ggplot(dummy.df, aes(x = dummy, y = X1, fill = Method)) +
      geom_boxplot(aes(fill = Method)) + 
  facet_grid(~Complexity) + 
    theme_light()  +
    theme(legend.position = 'bottom')  +
    guides(fill = guide_legend(nrow=1)) +
      geom_line(aes(x = dummy, 
                group=interaction(Pattern,nsim)), 
            size = 0.35, alpha = 0.35, colour = I("#525252"))  + 
    geom_point(aes(x = dummy, 
                group=interaction(Pattern,nsim)), 
               size = 0.35, alpha = 0.25, colour = I("#525252"))  +
   scale_x_discrete(labels = c("","X", "", "", "", "Y", "", "", "", "Z","","")) +
    xlab("Pattern") +
    scale_fill_brewer(breaks=c("A", "B", "C"), type="qual", palette="Paired")

dummy.df <- dd
dummy.df[nrow(dd) + 1:2,"Pattern"] <- unique(dd$Pattern)[-3]
dummy.df[nrow(dd) + 1:2,"Method"] <- "ZZZ"
dummy.df[nrow(dd) + 1:2,"Complexity"] <- c("High","Low")

dummy.df$dummy <- interaction(dummy.df$Method,dummy.df$Pattern)             
dummy.df$fill <- interaction(dummy.df$Method, dummy.df$n)
dummy.df$dummy <- interaction(dummy.df$fill, dummy.df$Pattern)
dummy.df$dummy <- factor(dummy.df$dummy, levels = levels(dummy.df$dummy)[-c(4, 12, 20, 24)])

dummy.df$dummy[361:362] <- "A.10.Z" ## dummy variables to get rid of NAs


theme_set(theme_bw(base_size = 14))

ggplot(dummy.df, aes(x = dummy, y = X1, fill = fill)) +
    geom_boxplot(aes(fill = fill),lwd=0.1,outlier.size = 0.01)  +
    facet_grid(~Complexity) +
    theme(legend.position = 'bottom')  +
    guides(fill = guide_legend(nrow=1)) +
    geom_line(aes(x = dummy, 
                  group=interaction(Pattern,nsim,n)), 
              size = 0.35, alpha = 0.35, colour = I("#525252"))  + 
    geom_point(aes(x = dummy, 
                   group=interaction(Pattern,nsim,n)), 
               size = 0.35, alpha = 0.25, colour = I("#525252"))  +
    scale_x_discrete(labels = c("X", "Y", "Z"), breaks = paste("A.10.", c("X", "Y", "Z"), sep = ""),drop=FALSE) +
    xlab("Pattern") +
    scale_fill_brewer(breaks= levels(dummy.df$fill)[-c(4,8)], type="qual", palette="Paired")

This yields the following plot. enter image description here

All is well, except with the legend. I would like the following: the dark colors to be in the First group titled "n=5" on the left, with "A", "B", "C" for the three dark colors, and the light colors to be to the right, in a Second group titled "n=10" on the right, with "A", "B", "C" for the three light colors. Sort of like in the link enter link description here above.

What I can not figure out is how to call the boxplot twice to mimic the solution there.

Is there a way to do this? Please feel free to let me know if the question is not clear.

Thanks again, in advance, for any help!


Solution

  • Adapting my answer on your former question this could be achieved like so:

    library(ggplot2)
    
    fill <- levels(dummy.df$fill)[-c(4,8)]
    fill <- sort(fill)
    labels <- gsub("\\.\\d+", "", fill)
    labels <- setNames(labels, fill)
    colors <- scales::brewer_pal(type="qual", palette="Paired")(6)
    colors <- setNames(colors, fill)
    
    library(ggnewscale)
    
    ggplot(dummy.df, aes(x = dummy, y = X1, fill = fill)) +
      geom_boxplot(aes(fill = fill), lwd=0.1,outlier.size = 0.01)  +
      scale_fill_manual(name = "n = 5", breaks= fill[grepl("5$", fill)], labels = labels[grepl("5$", fill)], values = colors,
                        guide = guide_legend(title.position = "left", order = 1)) +
      new_scale_fill() +
      geom_boxplot(aes(fill = fill), lwd=0.1,outlier.size = 0.01)  +
      scale_fill_manual(name = "n = 10", breaks = fill[grepl("10$", fill)], labels = labels[grepl("10$", fill)], values = colors,
                        guide = guide_legend(title.position = "left", order = 2)) +
      facet_grid(~Complexity) +
      theme(legend.position = 'bottom')  +
      guides(fill = guide_legend(nrow=1)) +
      geom_line(aes(x = dummy, 
                    group=interaction(Pattern,nsim,n)), 
                size = 0.35, alpha = 0.35, colour = I("#525252"))  + 
      geom_point(aes(x = dummy, 
                     group=interaction(Pattern,nsim,n)), 
                 size = 0.35, alpha = 0.25, colour = I("#525252"))  +
      scale_x_discrete(labels = c("X", "Y", "Z"), breaks = paste("A.10.", c("X", "Y", "Z"), sep = ""),drop=FALSE) +
      xlab("Pattern")
    #> Warning: Removed 2 rows containing non-finite values (new_stat_boxplot).