rggplot2ggpattern

Ggplot with multiple factors: How to implement pattern in the legend?


I managed to have quite nice legends for the first two parameters, but the third legend does not want to pop up as intended. I would like to see the pattern with black filling in the third legend element that describes the sequences.

Here an examplary data set:

df <- data.frame(Practice = factor(rep(c('A','B'), 216)),
                 Focus = factor(rep(c("high","high","low","low"), each = 216)), 
                 Session = factor(rep(c(1:6), each=72)),
                 Sequence = factor(rep(c('X','X','X','Y','Y','Y','Z','Z','Z'), 48)),
                 Hand = factor(rep(c('L','R','R','L'), 108)),
                 value = sample(0:100, 432, rep = TRUE)) %>%
  unite('group', c(Practice,Focus,Hand), remove=FALSE)

This is the plot:

ggplot(df, aes(x=Session, y=value, fill= Focus, pattern = Sequence)) +
  theme_classic() +
  facet_wrap(vars(group), nrow=4)  +
  geom_boxplot_pattern(outlier.shape=NA, position='dodge', key_glyph = 'rect',
    aes(alpha = Practice, fill = Focus,
      pattern_density = Sequence, pattern_angle = Sequence), 
    pattern = 'stripe', pattern_fill = 'white', pattern_colour = 'white', pattern_spacing = 0.02) +
  geom_point(size=0.25, position=position_jitterdodge(0.2), show.legend = FALSE)    +
  scale_alpha_discrete(range = c(1,0.3)) +
  scale_fill_brewer(palette = "Set1") +
  scale_pattern_density_manual(values = c(0,0.05,0.05), labels=c('different','mirror','practice')) + 
  scale_pattern_angle_manual(values = c(0,315,45), guide = "none") + 
  guides(alpha   = guide_legend(order=1, override.aes = list(fill='grey30', pattern='none')) ) + 
  guides(fill    = guide_legend(order=2, override.aes = list(pattern='none')) ) +
  guides(pattern_density = guide_legend(order=3, override.aes = list(
    fill='black',pattern = 'stripe', pattern_fill = 'white', pattern_colour = 'white', pattern_spacing = 0.02, pattern_density=0.05, pattern_angle=45) )) + 
  #guides(pattern_angle   = guide_legend(order=4, override.aes = list(fill='black', pattern_size=0.1)) ) +
  scale_y_continuous(breaks = seq(0,1500,200)) + ylab('Reaction time in ms') + geom_vline(xintercept=5.5,  color = "grey", linetype="dotted" ) #+

enter image description here


Solution

  • The main issue is that you have set key_glyph="rect" which does not support any patterns. Do display patterns in the legend you have to use one of the draw_key_xxx functions provided by ggpattern like draw_key_polygon_pattern or implement your own.

    Note: I dropped the facet_wrap to speed up the rendering time.

    library(ggplot2)
    library(ggpattern)
    
    ggplot(df, aes(x = Session, y = value, fill = Focus)) +
      theme_classic() +
      # facet_wrap(vars(group), nrow = 4) +
      geom_boxplot_pattern(
        outlier.shape = NA, position = "dodge",
        key_glyph = "polygon_pattern",
        aes(
          alpha = Practice,
          pattern_density = Sequence,
          pattern_angle = Sequence
        ),
        pattern = "stripe", pattern_fill = "white",
        pattern_colour = "white", pattern_spacing = 0.02
      ) +
      geom_point(
        size = 0.25,
        position = position_jitterdodge(0.2),
        show.legend = FALSE
      ) +
      geom_vline(xintercept = 5.5, color = "grey", linetype = "dotted") +
      scale_alpha_discrete(range = c(1, 0.3)) +
      scale_fill_brewer(palette = "Set1") +
      scale_pattern_density_manual(
        values = c(0, 0.05, 0.05),
        labels = c("different", "mirror", "practice")
      ) +
      scale_pattern_angle_manual(values = c(0, 315, 45), guide = "none") +
      guides(
        alpha = guide_legend(
          order = 1,
          override.aes = list(fill = "grey30", pattern = "none")
        ),
        fill = guide_legend(order = 2, override.aes = list(pattern = "none")),
        pattern_density = guide_legend(order = 3, override.aes = list(
          fill = "black", pattern = "stripe", pattern_fill = "white",
          pattern_colour = "white", pattern_spacing = 0.02,
          pattern_density = 0.05, pattern_angle = 45
        ))
      ) +
      scale_y_continuous(breaks = seq(0, 1500, 200)) +
      ylab("Reaction time in ms")
    

    enter image description here