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 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.
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.
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
scatter <- penguins %>%
na.omit() %>%
group_by(species) %>%
ggplot(aes(x = flipper_length_mm, y = body_mass_g, colour = species)) +
geom_point()
scatter
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")
Now we need to write a function that will …
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)
}
}
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.
The feather package is inspired by Australia birds.
library(feather)
feather_pal <- c("eastern_rosella", "blue_faced_parrot_finch", "cassowary" )
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)
}
}
walk(feather_pal, build_feather_plots)
The harrypotter package has palettes for each house and a few key characters.
library(harrypotter)
hp_pal <- c("LunaLovegood", "HermioneGranger", "HarryPotter")
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)
}
}
walk(hp_pal, build_hp_plots)
The wesanderson package has palettes inspired by Wes Anderson films.
library(wesanderson)
wes_pal <- c("FantasticFox1", "GrandBudapest1", "IsleofDogs1")
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)
}
}
walk(wes_pal, build_wes_plots)
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.
… 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!