SO much procrasti-coding going on today. I have deadlines looming and admin tasks that I don’t want to do, so here I find myself trying to work out how to iterate across colour palettes to easily find the prettiest one.

The coding is INDIRECTLY related to the talk I have to finish writing… so… here we go.

my goal

My goal is to work out how to make R show me lots of plots each using a different colour palette so I can decide which I like best without manually changing the scale_fill_manual() parameters.

This blog post was super useful.

https://data-chronicler.netlify.app/2020/01/08/2019-12-30-building-color-palette-proof-of-concepts-with-purrr-and-ggplot2/

load packages

library(tidyverse)
library(palmerpenguins)
library(patchwork) # to put both plots in the same image

theme_set(theme_classic()) # this was new to me- if you want all your plots to have a particular theme you can set it in the set up chunk


penguins <- penguins

The first step is to make a couple of basic plots (one bars and one scatter) to try our different palettes on.

make a basic bar plot

bars <- penguins %>%
  group_by(species) %>%
  summarise(mean_body_mass = mean(body_mass_g, na.rm = TRUE)) %>%
  ggplot(aes(x = species, y = mean_body_mass, fill = species)) +   
  scale_y_continuous(expand = c(0,0), limits = c(0,6000)) +
                      geom_col() 

bars

make a basic scatter plot

scatter <- penguins %>%
  na.omit() %>%
  group_by(species) %>%
  ggplot(aes(x = flipper_length_mm, y = body_mass_g, colour = species)) +
  geom_point() 

scatter

scico package

define your palettes

Pick a palette package and choose a few palettes to showcase. The scico package was one I hadn’t heard of before but it is maintained by Thomas Lin Pedersen so worth giving it a go.

library(scico)

scico_palettes <- c("devon", "lajolla", "lapaz")

build a function

Now we need to write a function that will …

  1. add a scico palette to the bar chart
  2. add a scico palette to the scatter chart
  3. use patchwork to combine the plots
  4. print the patchworked plots
  5. optionally save the plots to a folder
build_scico_plots <- function(scico_pal, save_plot = FALSE){

# add palette for basic bar chart
# note _d here is discrete, leave it off for continuous
  
scico_bar <- bars + scale_fill_scico_d(palette = scico_pal)

# add palette to basic scatter, 
# note _d here is discrete, leave it off for continuous

scico_scatter <- scatter + scale_color_scico_d(palette = scico_pal)

# use patchwork to combine plots and add a title
scico_patch <-  scico_bar/ scico_scatter + plot_annotation(title = scico_pal)

# print plot
print(scico_patch)

# optional save for later
if (save_plot == TRUE){
  ggsave(filename = here::here(paste0("figs/", scico_pal, ".jpg")),
       plot = scico_patch)
}

}

take your function for a “walk”

Then we can use walk() from the purrr package to iterate our new function across each of the palettes we have selected for testing. The walk() function is a bit like the map() function (in that it will run your function repeatedly across a list of things) but it works better for things like plots because it will leave output that you can look at.

It uses the format…

walk(listofthingstowalkacross, functiontoapply)

Here we are “walking” across the scico_palettes (which we defined above), applying your build_scico_plots function to each item in the list.

walk(scico_palettes, build_scico_plots)

OK so those options from the scico seem to have a lot of super light colours, which aren’t great. Lets try another palette package.

feather package

The feather package is inspired by Australia birds.

define your palettes

library(feather)

feather_pal <- c("eastern_rosella", "blue_faced_parrot_finch", "cassowary" )

build afunction

Unfortunately the way the feather package controls fill and colour is not identical to the scico package, so we have to change a few things in our function.

build_feather_plots <- function(feather_pal, save_plot = FALSE){

# add palette for basic bar chart

  
feather_bar <- bars + scale_fill_manual(values = get_pal(feather_pal))

# add palette to basic scatter, 

feather_scatter <- scatter + scale_color_manual(values = get_pal(feather_pal))

# use patchwork to combine plots and add a title
feather_patch <-  feather_bar/ feather_scatter + plot_annotation(title = feather_pal)

# print plot
print(feather_patch)

# optional save for later
if (save_plot == TRUE){
  ggsave(filename = here::here(paste0("figs/", feather_pal, ".jpg")),
       plot = feather_patch)
}

}

take your function for a “walk”

walk(feather_pal, build_feather_plots)

harrypotter package

The harrypotter package has palettes for each house and a few key characters.

define your palettes

library(harrypotter)

hp_pal <- c("LunaLovegood", "HermioneGranger", "HarryPotter")

build a function

Again the harrypotter package as custom functions for controlling fill and colour, so we have to adapt the function a bit.

build_hp_plots <- function(hp_pal, save_plot = FALSE){

# add palette for basic bar chart
# note _d here is discrete, leave it off for continuous
  
hp_bar <- bars + scale_fill_hp_d(option = hp_pal)

# add palette to basic scatter, 
# note _d here is discrete, leave it off for continuous

hp_scatter <- scatter + scale_color_hp_d(option = hp_pal)

# use patchwork to combine plots and add a title
hp_patch <-  hp_bar/ hp_scatter + plot_annotation(title = hp_pal)

# print plot
print(hp_patch)

# optional save for later
if (save_plot == TRUE){
  ggsave(filename = here::here(paste0("figs/", hp_pal, ".jpg")),
       plot = hp_patch)
}

}

take your function for a “walk”

walk(hp_pal, build_hp_plots)

wesanderson

The wesanderson package has palettes inspired by Wes Anderson films.

define your palettes

library(wesanderson)

wes_pal <- c("FantasticFox1", "GrandBudapest1", "IsleofDogs1")

build a function

Ahhh I’m seeing a pattern: the wesanderson package is more similar to feather in the way it controls fill and colour.

build_wes_plots <- function(wes_pal, save_plot = FALSE){

# add palette for basic bar chart

  
wes_bar <- bars + scale_fill_manual(values = wes_palette(wes_pal))

# add palette to basic scatter


wes_scatter <- scatter + scale_color_manual(values = wes_palette(wes_pal))

# use patchwork to combine plots and add a title
wes_patch <-  wes_bar/ wes_scatter + plot_annotation(title = wes_pal)

# print plot
print(wes_patch)

# optional save for later
if (save_plot == TRUE){
  ggsave(filename = here::here(paste0("figs/", scico_pal, ".jpg")),
       plot = scico_patch)
}

}

take your function for a “walk”

walk(wes_pal, build_wes_plots)

successes and challenges

Solving this problem took me a LONG time because I originally started trying to adapt code that was designed to iterate across variables and make scatter plots from different combinations. This post re automating exploratory plots was super interesting but not great at solving my palette problem. Unfortunately it took me a while to work out I was working with the wrong kind of code example.

Slightly different terms in my google search and I came up with this post, which was exactly what I needed. I wish I was better at picking the right google search terms straight up!

In the process, I learned that you can set your theme for ALL the plots in your set up chunk. Super useful…

theme_set(theme_classic())

By building functions to iterate across different palettes, I also learned that different colour palette packages control fill and colour in different ways.

Some (like feather and wesanderson) use scale_fill_manual() and others (like harrypotter, scico) have custom functions like scale_fill_hp(). These custom ones also distinguish between scale_fill_hp() for continuous and scale_fill_hp_d() for when you have discrete categories represented by colour.

next steps

… I really need to decide on a palette for the plots for my talk. I can now see the options but I’m no closer to a decision!