Search code examples
rggplot2ggmosaic

Using patterns instead of colours in mosaic plot with `ggmosaic` in `R`


Following THIS POST I was wondering if ggmosaic allows use of patterns rather than colours, maybe with ggpatterns?

From that previous post, the example dataset is:

dat = data.frame(
    Correct=c('no','yes','no','yes','no','yes','no','yes',
        'no','yes','no','yes','no','yes','no','yes'),
    Type=c('A','A','B','B','A','A','B','B',
        'A','A','B','B','A','A','B','B'),
    Level=c('1st','1st','1st','1st','2nd','2nd','2nd','2nd',
        '1st','1st','1st','1st','2nd','2nd','2nd','2nd'),
    Class=c('X','X','X','X','X','X','X','X',
        'Y','Y','Y','Y','Y','Y','Y','Y'),
    Percent=c(69.98,30.02,71.17,28.83,42.17,57.83,69.47,30.53,
        18.68,81.32,26.92,73.08,13.48,86.52,22.65,77.35)
)

Then, combine the original code with that from stefan:


library(ggmosaic)

mosaic1 <- ggplot(data=dat) +
    geom_mosaic(aes(weight=Percent, 
        x=product(Type, Level),
        conds=product(Class),
        fill=Correct)) +
    scale_y_productlist(breaks=c(.25,.75), labels=c('1st','2nd'),
        expand = c(0, 0.01)) +
  scale_x_productlist(expand=c(0,0.01)) +
    ggtitle('TITLE') +
    theme_tufte(base_family='sans') +
    theme(axis.text.x=element_text(angle=45, hjust=1, vjust=1, size=10),
        axis.title=element_text(size=11),
        legend.text=element_text(size=10),
        legend.title=element_text(size=11))
mosaic1

How can one replace colours with patterns, e.g., using ggpattern?


Solution

  • Another option would be to use the new features introduced with ggplot2 3.5.0 (and R >= 4.2.0) which bring native support of patterns to ggplot2. There is still some room for a more user-friendly API to specify patterns, i.e. as of the moment we have to specify the patterns from scratch using grobs, but it works well with the default geoms and scales, and also with ggmosaic.

    library(ggplot2)
    library(ggmosaic)
    library(ggthemes)
    library(grid)
    
    packageVersion("ggplot2")
    #> [1] '3.5.0'
    packageVersion("ggmosaic")
    #> [1] '0.3.4'
    
    patterns <- list(
      pattern(
        rectGrob(x = c(0, 1), y = c(0.25, 0.75), width = 1, height = 0.5),
        height = unit(5, "mm"), 
        extend = "repeat",
        gp = gpar(fill = "#b2182b")
      ),
      pattern(
        rectGrob(x = c(0.25, 0.75), y = c(0.25, 0.75), width = 0.5, height = 0.5),
        width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat",
        gp = gpar(fill = "#1b7837")
      )
    )
    
    ggplot(data = dat) +
      geom_mosaic(aes(
        weight = Percent,
        x = product(Type, Level),
        conds = product(Class),
        fill = Correct
      ), color = "grey40") +
      scale_fill_manual(
        values = patterns
      ) +
      scale_y_productlist(
        breaks = c(.25, .75), 
        labels = c("1st", "2nd"),
        expand = c(0, 0.01)
      ) +
      scale_x_productlist(expand = c(0, 0.01)) +
      ggtitle("TITLE") +
      theme_tufte(base_family = "sans") +
      theme(
        axis.text.x = element_text(
          angle = 45, hjust = 1,
          vjust = 1, size = 10
        ),
        axis.title = element_text(size = 11),
        legend.text = element_text(size = 10),
        legend.title = element_text(size = 11)
      )
    

    UPDATE Using linesGrob for the patterns we could get vertical and horizontal lines using this specification for the patterns:

    patterns <- list(
      pattern(
        linesGrob(
          x = c(0, 1), y = c(0.5, 0.5)
        ),
        height = unit(3, "mm"),
        extend = "repeat",
        gp = gpar(col = "#b2182b", lwd = unit(5, "mm"), fill = NA)
      ),
      pattern(
        linesGrob(
          x = c(0.5, 0.5), y = c(0, 1)
        ),
        width = unit(3, "mm"),
        extend = "repeat",
        gp = gpar(col = "#1b7837", lwd = unit(5, "mm"), fill = NA)
      )
    )
    

    enter image description here