Styling Plots {#plotstyle}

knitr::opts_chunk$set(
  echo = FALSE,
  warning = FALSE
)
library(ggthemes)

Aesthetics

Colour/Fill

The colour argument changes the point and line colour, while the fill argument changes the interior colour of shapes. Type colours() into the console to see a list of all the named colours in R. Alternatively, you can use hexadecimal colours like "#FF8000" or the rgb() function to set red, green, and blue values on a scale from 0 to 1.

Hover over a colour to see its R name.

name <- colours(TRUE)
rgb <- col2rgb(name) 
hsv <- rgb2hsv(rgb)
hex <- as.hexmode(rgb) %>% as.character() %>% 
  apply(2, paste, collapse = "")

colors <- tibble(name = name,
       hue = hsv[1, ] %>% round(2),
       sat = hsv[2, ] %>% round(2),
       val = hsv[3, ] %>% round(2),
       hex = hex) %>%
  arrange(hue, sat, val)

glue::glue("    <li style='background-color: #{colors$hex};'><span>{colors$name}</span></li>") %>%
  paste(collapse = "\n") %>%
  paste0("\n<ul class='colordemo'>\n", ., "\n</ul>\n") %>%
  cat()

Alpha

The alpha argument changes transparency (0 = totally transparent, 1 = totally opaque).

alphas <- crossing(alpha = seq(0, 1, .1), y = 0:1)
ggplot(alphas, aes(x = alpha, y = y, alpha = I(alpha), 
                   color = as.factor(y))) +
  geom_hline(yintercept = 0, size = 5, color = "dodgerblue") +
  geom_hline(yintercept = 1, size = 5, color = "black") +
  geom_point(size = 20, show.legend = FALSE) +
  scale_x_continuous("alpha", breaks = alphas$alpha) +
  scale_y_continuous("", breaks = -1:2, limits = c(-1, 2)) +
  scale_color_manual(values = c("black", "dodgerblue")) +
  theme_minimal(base_size = 20) +
  theme(axis.text.y = element_blank(),
        panel.grid.minor = element_blank())

Shape

The shape argument changes the shape of points.

shapes <- tibble(shape = 1:25, y = 0)
ggplot(shapes, aes(x = shape, y = y, shape = I(shape))) +
  geom_point(size = 8) +
  scale_x_continuous("", breaks = shapes$shape) +
  scale_y_continuous("", breaks = 0) +
  theme_minimal(base_size = 20) +
  theme(axis.text.y = element_blank(),
        panel.grid.minor = element_blank())

Linetype

You can probably guess what the linetype argument does.

lines <- crossing(linetype = 1:6, size = c(0.25, 0.5, 1, 2)) %>% 
  mutate(x = linetype)
ggplot(lines) +
  geom_vline(aes(xintercept = linetype, 
                 linetype = I(linetype),
                 size = I(size))) +
  scale_x_continuous("linetype", breaks = 1:6, 
                     expand = expansion(add = 1)) +
  facet_wrap(~size, nrow = 1, labeller = label_both) +
  theme_minimal(base_size = 20) +
  theme(axis.text.y = element_blank(),
        panel.grid.minor = element_blank())

Palettes

palette_demo <- function(levels, seed = 8675309) {
  set.seed(seed)

  dat <- faux::sim_design(
    within = list(level = 1:levels),
    between = list(condition= c("control", "experimental")),
    n = 50, dv = "score",
    plot = FALSE, long = TRUE)

  ggplot(dat, aes(x = level, 
                  y = score, 
                  color = level, 
                  fill = level)) + 
    geom_violin(alpha = 0.8, color = "black") +
    stat_summary(fun = mean) +
    scale_x_discrete(name = "") +
    guides(color = "none", fill = "none") +
     theme(axis.text.y = element_blank(),
           axis.title.y = element_blank(),
           axis.ticks.y = element_blank())
}

palette_plot <- function(g, p) { 
  g + scale_color_brewer(palette = p) +
    scale_fill_brewer(palette = p) +
    ggtitle(glue::glue("palette = \"{p}\""))
}

viridis_d_plot <- function(g, option = "viridis") { 
  g + scale_color_viridis_d(option = option) +
    scale_fill_viridis_d(option = option) +
    ggtitle(glue::glue("option = \"{option}\""))
}

Discrete palettes change depending on the number of categories.

plots <- lapply(1:8, palette_demo)
wrap_plots(plots, ncol = 2)

Viridis Palettes

Viridis palettes are very good for colourblind-safe and greyscale-safe plots. The work with any number of categories, but are best for larger numbers of categories or continuous colours.

Discrete Viridis Palettes

Set r glossary("discrete") viridis colours with scale_colour_viridis_d() or scale_fill_viridis_d() and set the option argument to one of the options below. Set direction = -1 to reverse the order of colours.

options <- list("magma", "inferno", "plasma", "viridis", "cividis")

g <- palette_demo(5)
plots5 <- lapply(options, viridis_d_plot, g = g)

g <- palette_demo(15)
plots15 <- lapply(options, viridis_d_plot, g = g)

( wrap_plots(plots5, ncol = 1) | 
  wrap_plots(plots15, ncol = 1)) +
  plot_layout(widths = c(1, 3))

::: {.info data-latex=""} If the end colour is too light for your plot or the start colour too dark, you can set the begin and end arguments to values between 0 and 1, such as r hl(scale_colour_viridis_c(begin = .1, end = .9)). :::

Continuous Viridis Palettes

Set r glossary("continuous") viridis colours with scale_colour_viridis_c() or scale_fill_viridis_c() and set the option argument to one of the options below. Set direction = -1 to reverse the order of colours.

options <- list("magma", "inferno", "plasma", "viridis", "cividis")

set.seed(8675309)
g <- faux::rnorm_multi(
    n = 10000,
    vars = 2, 
    r = 0.5) %>%
  ggplot(aes(X1, X2)) + 
  theme(axis.text.y = element_blank(),
        axis.title.y = element_blank(),
        axis.ticks.y = element_blank(), 
        axis.text.x = element_blank(),
        axis.title.x = element_blank(),
        axis.ticks.x = element_blank())


viridis_c_plot <- function(g, option, geom = geom_hex) {
  g + scale_color_viridis_c(option = option) +
    geom() +
    scale_fill_viridis_c(option = option) +
    ggtitle(glue::glue("option = \"{option}\""))
}

hex_plots <- lapply(options, viridis_c_plot, g = g)
wrap_plots(hex_plots, nrow = 3)

Brewer Palettes

Brewer palettes give you a lot of control over plot colour and fill. You set them with scale_color_brewer() or scale_fill_brewer() and set the palette argument to one of the palettes below. Set direction = -1 to reverse the order of colours.

Qualitative Brewer Palettes

These palettes are good for r glossary("categorical") data with up to 8 categories (some palettes can handle up to 12). The "Paired" palette is useful if your categories are arranged in pairs.

palettes <- list("Accent", "Dark2", "Paired", "Pastel1", "Pastel2", "Set1", "Set2", "Set3")

g <- palette_demo(12)
plots <- lapply(palettes, palette_plot, g = g)
wrap_plots(plots, ncol = 2)

Sequential Brewer Palettes

These palettes are good for up to 9 r glossary("ordinal") categories with a lot of categories.

palettes <- c("Reds", "RdPu",
              "Oranges", "OrRd", 
              "YlOrRd", "YlOrBr", "YlGn", "YlGnBu",
              "Greens", "GnBu",
              "Blues", "BuGn", "BuPu", 
              "Purples", "PuRd", "PuBu", "PuBuGn",
              "Greys")

g <- palette_demo(9)
plots <- lapply(palettes, palette_plot, g = g)
wrap_plots(plots, ncol = 2)

Diverging Brewer Palettes

These palettes are good for r glossary("ordinal") categories with up to 11 levels where the centre level is a neutral or baseline category and the levels above and below it differ in an important way, such as agree versus disagree options.

palettes <- c("BrBG", "PiYG", "PRGn", "PuOr", "RdBu", "RdGy", "RdYlBu", "RdYlGn", "Spectral")

g <- palette_demo(11)
plots <- lapply(palettes, palette_plot, g = g)
wrap_plots(plots, ncol = 2)

Themes

r pkg("ggplot2") has 8 built-in themes that you can add to a plot like plot + theme_bw() or set as the default theme at the top of your script like theme_set(theme_bw()).

```r themes."} g <- palette_demo(2) + facet_wrap(~condition)

themes <- c("theme_bw", "theme_classic", "theme_dark", "theme_gray", "theme_light", "theme_linedraw", "theme_minimal", "theme_void")

plots <- lapply(themes, function(f) { g + get(f)() + ggtitle(glue::glue("{f}()")) }) wrap_plots(plots, ncol = 2)

### ggthemes

You can get more themes from add-on packages, like `r pkg("ggthemes", "https://yutannihilation.github.io/allYourFigureAreBelongToUs/ggthemes/")`. Most of the themes also have custom `scale_` functions like `scale_colour_economist()`. Their website has extensive examples and instructions for alternate or dark version sof these themes.

```r themes."}
g <- palette_demo(2) + facet_wrap(~condition)

themes <- c("theme_wsj", "theme_tufte", "theme_stata", "theme_gdocs", "theme_fivethirtyeight", "theme_economist", "theme_igray", "theme_hc", "theme_few", "theme_map", "theme_excel", "theme_calc", "theme_economist_white", "theme_excel_new", "theme_pander", "theme_solarized", "theme_solarized_2") %>% sort() %>% setNames(., .)

plots <- lapply(themes, function(f) {
  scale_colour <- tryCatch({
    get(gsub("theme_","scale_colour_", gsub("_2", "", f)))()
  }, error = function(e) {
    return(NULL)
  })

  scale_fill <- tryCatch({
    get(gsub("theme_","scale_fill_", gsub("_2", "", f)))()
  }, error = function(e) {
    return(NULL)
  })

  g + get(f)() + 
    ggtitle(glue::glue("{f}()")) + 
    scale_colour + 
    scale_fill
})

wrap_plots(plots, ncol = 2)


PsyTeachR/reprores-v2 documentation built on Sept. 26, 2022, 10:06 a.m.