Data Visualization II

How to make publication-ready plots

Lennart Klein & Prof. Dr. Christian Fischer

University of Tübingen

Jul 26, 2023

The Basics 🌱

The Grammar of Graphics

data %>% 
  ggplot(mapping = aes(<MAPPINGS>)) + 
  <GEOM_FUNCTION>(mapping = aes(<MAPPINGS>), 
                  stat = <STAT>, 
                  position = <POSITION>) + 
  <COORDINATE_FUNCTION> + 
  <FACET_FUNCTION> + 
  <SCALE_FUNCTION> + 
  <THEME_FUNCTION>

From Data to Viz 📈

Planning

  • Number of Variables (1, 2, 3, …)

  • Type of Variables (Discrete, Continuous, Time)

  • Kind of Visualization (e.g., Distribution, Relationship, Change, etc.)


  • ➡ What’s the goal of your visualization? What do you want to show?

Choose your Plot Type / Geom

Styling Tipps

Example Data

# pak::pkg_install("tidyverse")
library(tidyverse)

dat <- readRDS(here::here("data", "TWLZ_Seminar_Sample.rds"))

Example I

dat %>%
  ggplot(aes(x = is_teacher, fill = is_original)) +
  geom_bar() +
  labs(x = NULL, y = "Frequency") +
  scale_x_discrete(labels = c("Non-teacher", "Teacher"))

Example I: Custom Bar Width

dat %>%
  ggplot(aes(x = is_teacher, fill = is_original)) +
  geom_bar(width = 0.5) + # between 1.0 - 0.0
  labs(x = NULL, y = "Frequency") +
  scale_x_discrete(labels = c("Non-teacher", "Teacher"))

Example I: Better Scales

dat %>%
  ggplot(aes(x = is_teacher, fill = is_original)) +
  geom_bar(width = 0.5) + # between 1.0 - 0.0
  labs(x = NULL, y = "Frequency") +
  scale_x_discrete(labels = c("Non-teacher", "Teacher")) +
  scale_y_continuous(labels = scales::label_comma()) # scales::label_XYZ()

Example I: Custom Legend

dat %>%
  ggplot(aes(x = is_teacher, fill = is_original)) +
  geom_bar(width = 0.5) + # between 1.0 - 0.0
  labs(x = NULL, y = "Frequency") +
  scale_x_discrete(labels = c("Non-teacher", "Teacher")) +
  scale_y_continuous(labels = scales::label_comma()) +
  scale_fill_discrete("Original") + # Legend Title
  theme(legend.position = "bottom") # Legend Position

Example II

dat %>%
  ggplot(aes(x = year, y = retweet_count)) +
  stat_summary(fun.data = "mean_se")

Example II: Custom Axis Labels

dat %>%
  ggplot(aes(x = year, y = retweet_count)) +
  stat_summary(fun.data = "mean_se") +
  labs(x = NULL, y = "Retweet count") # NULL removes the axis

Example II: Custom Axis Breaks

dat %>%
  ggplot(aes(x = year, y = retweet_count)) +
  stat_summary(fun.data = "mean_se") +
  labs(x = NULL, y = "Retweet count") + # NULL removes the axis
  scale_x_discrete(breaks = seq(2008, 2020, 2))

Example II: theme_apa()

# install.packages(papaya)
dat %>%
  ggplot(aes(x = year, y = retweet_count)) +
  stat_summary(fun.data = "mean_se") +
  labs(x = NULL, y = "Retweet count") +
  scale_x_discrete(breaks = seq(2008, 2020, 2)) +
  papaja::theme_apa(base_size = 16) # base_size = size of all fonts

Example II: Custom Theming

  • create a standard theme to reuse for all plots
custom_theming <- theme(
  axis.text = element_text(color = "black"),
  axis.title = element_text(color = "black")
  # add other
)

Example II: Custom Theming

dat %>%
  ggplot(aes(x = year, y = retweet_count)) +
  stat_summary(fun.data = "mean_se") +
  labs(x = NULL, y = "Retweet count") +
  scale_x_discrete(breaks = seq(2008, 2020, 2)) +
  papaja::theme_apa(base_size = 16) +
  custom_theming

Example II: Before

Example II: After

Colorblind-friendly palettes

  • ggplot2 default color palette
colorBlindness::displayAllColors(scales::hue_pal()(5))

Colorblind-friendly palettes

  • alternative viridis color palette
colorBlindness::displayAllColors(viridis::viridis_pal()(5))

Colorblind-friendly palettes

  • or the Okabe-Ito (2008) color palette
# pak::pkg_install("clauswilke/colorblindr")
colorBlindness::displayAllColors(colorblindr::palette_OkabeIto_black)

Colorblind-friendly palettes

  • accessible as scale_ functions for color and fill
scale_color_viridis_d() # discrete
scale_color_viridis_c() # continous

scale_fill_viridis_d() # discrete
scale_fill_viridis_c() # continous

Export 🚀

Export Formats

  • .png (Google Docs)
  • .pdf (Word, LaTeX)
# saves the last plot
ggsave("plots/plot1.png",
  width = 12, height = 10, units = "cm",
  dpi = 600, pointsize = 12
) # 'dpi' based on journal guidelines


ggsave("plots/plot1.pdf",
  width = 12, height = 10, units = "cm",
  family = "serif", # font family: "serif" or "sans"
  pointsize = 12
) # size of font (should be the same as paper)

Adjusting Plot Sizes

Use ggview() from the {ggview} package to quickly adjust plot sizes.

Housekeeping 🏡

Summer Break Office Hours

  • Lennart’s Zoom Office Hours, once a week