#!/usr/bin/env RScript # Acme colours setup ---- # This is all the stuff we set up last time. library("dplyr") library("tidyr") library("ggplot2") library("colorspace") .acme_colours <- c( red = "#eb3b5a", orange = "#fa8231", yellow = "#f7b731", green = "#20bf6b", topaz = "#0fb9b1", light_blue = "#2d98da", dark_blue = "#3867d6", purple = "#8854d0" ) acme_colours <- function(index = NULL, named = FALSE) { # Default to everything if (is.null(index)) { index <- names(.acme_colours) } # This works with integer or character values return_value <- .acme_colours[index] if (!named) { names(return_value) <- NULL } return(return_value) } acme_colour_names <- function() { names(.acme_colours) } acme_palette <- function() { acme_colour_length <- length(acme_colours()) function(n) { stopifnot(n <= acme_colour_length) return(acme_colours(1:n)) } } scale_colour_acme <- function(...) { ggplot2::discrete_scale( aesthetics = "colour", scale_name = "acme", palette = acme_palette(), ... ) } # Set up data ---- mileage <- mpg %>% filter(manufacturer %in% c("toyota", "honda", "nissan", "subaru", "hyundai")) %>% group_by(manufacturer, year) %>% summarise(mileage = mean(cty)) # Example 1 ---- # No primary series ggplot(mileage, aes(x = year, y = mileage, colour = manufacturer)) + geom_line() + scale_colour_acme() + theme_minimal() ggsave(filename = "plot_without_primary.png", width = 5, height = 5) # Set up a "primary" scale scale_colour_acme <- function(primary = NULL, ...) { scale <- ggplot2::discrete_scale( aesthetics = "colour", scale_name = "acme", palette = acme_palette(), ... ) if (!is.null(primary)) { scale$old_map <- scale$map scale$breaks <- function(values) { c( primary, setdiff(values, primary) ) } scale$map <- function(self, x, limits = self$get_limits()) { limits <- c( primary, setdiff(limits, primary) ) self$old_map(x = x, limits = limits) } } return(scale) } # Example 2 ---- # Ensure "toyota" is plotted in red ggplot(mileage, aes(x = year, y = mileage, colour = manufacturer)) + geom_line() + scale_colour_acme(primary = "toyota") + theme_minimal() ggsave(filename = "plot_with_primary.png", width = 5, height = 5) # Build primary/other scales ---- scale_colour_acme <- function(primary = NULL, other = NULL, ...) { scale <- ggplot2::discrete_scale( aesthetics = "colour", scale_name = "acme", palette = acme_palette(), ... ) if (!is.null(primary)) { scale$old_map <- scale$map scale$breaks <- function(values) { c( primary, setdiff(values, primary) ) } scale$map <- if (is.null(other)) { function(self, x, limits = self$get_limits()) { limits <- c( primary, setdiff(limits, primary) ) self$old_map(x = x, limits = limits) } } else { function(self, x, limits = self$get_limits()) { ifelse( x == primary, acme_colours(1), other ) } } } return(scale) } # Example 3 ---- # Plot "toyota" in red, everything else in light grey ggplot(mileage, aes(x = year, y = mileage, colour = manufacturer)) + geom_line() + scale_colour_acme(primary = "toyota", other = "#AAAAAA") + theme_minimal() + theme(legend.position = "none") ggsave(filename = "plot_with_other.png", width = 5, height = 5) # Appying primary/other to other scales ---- scale_size_specific <- function(..., .default) { scale_map <- c(...) stopifnot(all(names(scale_map) != "")) scale <- scale_size_manual(guide = "none") scale$map <- function(self, x, limits = self$get_limits()) { mapping <- scale_map[x] mapping[is.na(mapping)] <- .default mapping } return(scale) } scale_alpha_specific <- function(..., .default) { scale_map <- c(...) stopifnot(all(names(scale_map) != "")) scale <- scale_alpha_manual(guide = "none") scale$map <- function(self, x, limits = self$get_limits()) { mapping <- scale_map[x] mapping[is.na(mapping)] <- .default mapping } return(scale) } # Example 4 ---- # Plot "toyota" in red and size 1, everything else light grey and size 0.5 ggplot(mileage, aes(x = year, y = mileage, colour = manufacturer, size = manufacturer, alpha = manufacturer)) + geom_line() + scale_colour_acme(primary = "toyota", other = "#AAAAAA") + scale_size_specific("toyota" = 1, .default = 0.5) + scale_alpha_specific("toyota" = 1, .default = 0.8) + theme_minimal() + theme(legend.position = "none") ggsave(filename = "plot_with_specific.png", width = 5, height = 5) # Example 5 ---- # Plot "toyota" in red and size 1, everything else gets a colour but is fainter and thinner ggplot(mileage, aes(x = year, y = mileage, colour = manufacturer, size = manufacturer, alpha = manufacturer)) + geom_line() + scale_colour_acme(primary = "toyota") + scale_size_specific("toyota" = 1, .default = 0.5) + scale_alpha_specific("toyota" = 1, .default = 0.8) + theme_minimal() ggsave(filename = "plot_with_specific_and_colours.png", width = 5, height = 5)