Before we start

  1. Please complete the Student Voice section on NOW.
  2. Complete last week’s exercises.
  3. This is the last session on ggplot2. We will move one to shiny apps next week.

General outline for weeks 2 – 5

  • Week 2: Principles of data visualisation
  • Week 3: Grammar of graphics; aesthetics and attributes
  • Week 4: Major visualisation tools
  • Week 5: Customising visualisations (scales, themes, and labels)

Objectives for today

By the end of this session, you should be able to \(\dots\)

  1. Customise ggplot2 visualisations using scales, themes, and labels to enhance clarity and impact.
  2. Apply design principles (e.g., Tufte’s guidelines) to reduce chartjunk and improve interpretability.
  3. Tailor visualisations for different audiences and media, ensuring accessibility and effective communication.

Download exercises from Week 5 folder on NOW and move them into your R-project directory.

Why customisation matters in data visualisation

  1. Visuals shape understanding: a well-designed plot doesn’t just show data; it tells a story. Ensure that the story is clear, accurate, and compelling.
  2. Audiences vary: tailor your visuals to the audience’s needs and expectations.
  3. Medium matters: plots for journal articles, posters, or interactive dashboards each require different design choices.
  4. Avoiding misinterpretation: poor design choices – like misleading axes or cluttered legends – can obscure key insights or even lead to incorrect conclusions.
  5. Accessibility and inclusivity: thoughtful use of colour, labels, and themes can make your plots more accessible (e.g. people with visual impairments).

Maximising clarity and minimising chartjunk through thoughtful design choices!

Revisiting Tufte’s Principles (Tufte, 2001):

  • Data-Ink ratio: Maximise the proportion of ink that represents data.
  • Chartjunk: Avoid unnecessary decoration (3D effects, heavy gridlines, etc.).
  • Small multiples: Use consistent scales and layout to compare across categories.
  • Narrative graphics: Use annotations and labels to guide interpretation.

Applying Tufte to ggplot2

How does ggplot2 supports Tufte’s principles:

  • Minimal and custom themes to improve readability (theme_minimal(), theme_void())
  • Transform and resize scales to reduce distortion
  • Direct labeling vs legends to make plots self-explanatory
  • Faceting for small multiples (facet_wrap(), facet_grid())
  • Reduce overplotting: position_dodge(), alpha = .5, size = .5
  • Inclusive colour schemes, grey scale, combining aesthetics

The grammar of graphics implemented in ggplot2 by Hadley Wickham aligns with Tufte’s principles.

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs()

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(title = "My scatter plot")

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(title = "My scatter plot", 
       subtitle = "I'm a subtitle")

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(caption = "Caption for data source")

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(tag = "A")

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(x = "Production duration in msecs", 
       y = "Reaction time in msecs")

Changing text: labs

  • title
  • subtitle
  • caption
  • tag
  • x
  • y
  • colour, shape, linetype, fill

ggplot(d_spellname, aes(y = rt, x = dur,
                          colour = modality)) +
  geom_point() + 
  labs(colour = "Legend\ntitle:")

Exercise 1: Changing text

Complete RMarkdown document 1_add_labs.Rmd

Changing text: legend keys

  • scale_colour_discrete
  • scale_colour_continuous
  • scale_colour_manual
  • or any other aesthetic instead of colour

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) +
  geom_point() +  
  scale_colour_discrete(
    labels = c("Spoken output", "Written output")) 

Changing text: legend keys

  • Change colour values manually
  • Colour names: link
  • ggthemes

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) +
  geom_point() +  
  scale_colour_manual(
    labels = c("Spoken output", "Written output"),
    values = c("firebrick", "turquoise2")

Changing text: legend keys

  • Change colour values manually
  • Colour names: link
  • ggthemes

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) +
  geom_point() +  
  scale_colour_manual(
    labels = c("Spoken output", "Written output"),
    values = c("firebrick", "turquoise2"))

Changing text: legend keys

  • Change colour values manually
  • Colour names: link
  • ggthemes
# RGB codes of "colorblind" function
mycolours <- c("#000000", "#E69F00", "#56B4E9", "#009E73", 
               "#F0E442", "#0072B2", "#D55E00", "#CC79A7")

# RGB codes of "colorblind" function
scales::show_col(colorblind_pal()(8))

Changing text: legend keys

  • Change colour values manually
  • Colour names: link
  • ggthemes

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) +
  geom_point() +  
  scale_colour_manual(
    labels = c("Spoken output", "Written output"),
    values = mycolours[1:2])

Changing text: legend keys

  • Change colour values manually
  • Colour names: link
  • ggthemes

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) +
  geom_point() +  
  scale_colour_colorblind(
    labels = c("Spoken output", "Written output"))

Exercise 2: Customising colour aesthetics

Complete the RMarkdown 2_customising_aes.Rmd

Changing text: strips

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality)

Changing text: strips

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both)

Changing text: strips

d_spellname <- mutate(d_spellname, 
                    modality = recode(modality, 
                    "speech" = "Spoken output",
                    "writing" = "Written output"))

Changing text: strips

d_spellname <- mutate(d_spellname, 
                    modality = recode(modality, 
                    "speech" = "Spoken output",
                    "writing" = "Written output"))

Themes

  • Specify appearance of non-data related ink
  • Can be done manually using themes() or using wrapper functions
  • All ggplot2 wrappers:
[1] "theme_bw"       "theme_classic"  "theme_dark"     "theme_grey"    
[5] "theme_light"    "theme_linedraw" "theme_minimal"  "theme_void"    
  • e.g. ggthemes package for more themes:
 [1] "theme_base"            "theme_calc"            "theme_clean"          
 [4] "theme_economist"       "theme_economist_white" "theme_excel"          
 [7] "theme_excel_new"       "theme_few"             "theme_fivethirtyeight"
[10] "theme_foundation"      "theme_gdocs"           "theme_hc"             
[13] "theme_map"             "theme_pander"          "theme_par"            
[16] "theme_solarized"       "theme_solarized_2"     "theme_solid"          
[19] "theme_stata"           "theme_stata_base"      "theme_stata_colors"   
[22] "theme_tufte"           "theme_wsj"            

Themes (ggplot2 default)

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  facet_grid(~modality) +
  theme_grey(base_size = 11)

Themes

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  facet_grid(~modality) +
  theme_minimal(base_size = 14)

Themes

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  facet_grid(~modality) +
  theme_light(base_size = 14)

Themes

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  facet_grid(~modality) +
  theme_dark(base_size = 14)

Themes (ggthemes)

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  facet_grid(~modality) +
  theme_clean()

Themes

  • axis
  • legend
  • panel
  • plot
  • strip

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  theme()

Themes: axis

  • axis.text
    • axis.text.x
    • axis.text.y
  • axis.title
    • axis.title.x
    • axis.title.y

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  theme(axis.text = element_text(face = "italic"))

Themes: axis

  • axis.text
    • axis.text.x
    • axis.text.y
  • axis.title
    • axis.title.x
    • axis.title.y

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  theme(axis.title = element_text(face = "bold"))

Themes: axis

  • axis.text
    • axis.text.x
    • axis.text.y
  • axis.title
    • axis.title.x
    • axis.title.y

ggplot(d_spellname, aes(y = rt, x = dur)) + 
  geom_point() +
  theme(axis.title.y = element_text(face = "bold"))

Themes: legend

  • legend.background
  • legend.margin
  • legend.spacing
  • legend.key
  • legend.text
  • legend.title
  • legend.position
  • legend.orientation
  • legend.justification
  • legend.box

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) + 
  geom_point() +
  theme()

Themes: legend

  • legend.background
  • legend.margin
  • legend.spacing
  • legend.key
  • legend.text
  • legend.title
  • legend.position
  • legend.orientation
  • legend.justification
  • legend.box

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) + 
  geom_point() +
  theme(legend.position = "top")

Themes: legend

  • legend.background
  • legend.margin
  • legend.spacing
  • legend.key
  • legend.text
  • legend.title
  • legend.position
  • legend.orientation
  • legend.justification
  • legend.box

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality)) + 
  geom_point() +
  theme(legend.position = "top",
        legend.justification = "right")

Themes: legend

  • legend.background
  • legend.margin
  • legend.spacing
  • legend.key
  • legend.text
  • legend.title
  • legend.position
  • legend.orientation
  • legend.justification
  • legend.box

ggplot(d_spellname, aes(y = rt, x = dur, colour = modality))+
  geom_point() + 
  theme(legend.position = c(.15,.8))

Themes: panel

  • panel.background
  • panel.border
  • panel.spacing
  • panel.grid
    • panel.grid.major
    • panel.grid.minor

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  theme()

Themes: panel

  • panel.background
  • panel.border
  • panel.spacing
  • panel.grid
    • panel.grid.major
    • panel.grid.minor

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  theme(panel.background = element_blank())

Themes: plot

  • plot.background
  • plot.margin
  • plot.title
  • plot.subtitle
  • plot.caption
  • plot.tag

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() +
  theme()

Themes: plot

  • plot.background
  • plot.margin
  • plot.title
  • plot.subtitle
  • plot.caption
  • plot.tag

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  theme(plot.background = element_rect(fill = "pink"))

Themes: plot

  • plot.background
  • plot.margin
  • plot.title
  • plot.subtitle
  • plot.caption
  • plot.tag

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  theme(plot.background = element_rect(fill = "pink"),
        plot.margin = unit(c(2,2,2,2), "cm"))

Themes: plot

  • plot.background
  • plot.margin
  • plot.title
  • plot.subtitle
  • plot.caption
  • plot.tag

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  labs(title = "I'm a title") +
  theme(plot.title = element_text(colour = "pink"))

Themes: plot

  • plot.background
  • plot.margin
  • plot.title
  • plot.subtitle
  • plot.caption
  • plot.tag

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  labs(caption = "I'm a caption") +
  theme(plot.caption = element_text(face = "italic"))

Themes: facet strips

  • strip.background
  • strip.placement
  • strip.text

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both) +
  theme()

Themes: strip.background

  • strip.background
  • strip.placement
  • strip.text

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both) +
  theme(strip.background = element_blank())

Themes: strip.background

  • strip.background
  • strip.placement
  • strip.text

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both) +
  theme(strip.background = element_rect(fill = "forestgreen"))

Themes: strip.text

  • strip.background
  • strip.placement
  • strip.text

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both)+
  theme(strip.background = element_rect(fill = "forestgreen"),
        strip.text = element_text(colour = "white", hjust = 0))

Themes: strip.text

  • strip.background
  • strip.placement
  • strip.text

ggplot(d_spellname, aes(y = rt, x = dur)) +
  geom_point() + 
  facet_grid(~modality, labeller = label_both) +
  theme(strip.background = element_rect(fill = "forestgreen"),
        strip.text = element_text(colour = "white", hjust = 0, 
                                  face = "bold", size = 16, 
                                  angle = 180))

Exercise 3: creating your own theme

Complete RMarkdown 3_defining_themes.Rmd

Saving your plot

ggsave("name of plot.png", width = 5, height = 5)
  • .eps, .pdf, .svg, .wmf, .png, .jpg, .bmp, .tiff
  • sizes requires some manual adjustment (or fig.width in RMarkdown)
  • make sure fonts are not too small / large
  • keep the aspect ratio sensible
  • or export function in plots panel

Useful resources for data visualisation

Reading

Formative assessment

Task: Select a behavioural dataset—-i.e., data related to human behaviour (e.g., psychological experiments, survey responses, reaction times, decision-making patterns, social media behaviour, etc.).

  • Create 3-4 visualisations using different techniques (e.g., boxplot, scatterplot, density plot).
  • Include brief commentary on:
    • What each visualisation highlights about the data?
    • Why each visualisation was chosen?
    • How each visualisation adheres to principles of effective visualisation (e.g., Tufte’s guidelines)?
    • To what extent the each visualisation may (or may not) obscure the data.
  • Deadline: 31st October 2025
  • Length: max 1,000 words

Feedback focus:

  • Clarity and effectiveness of visualisations.
  • Code quality and reproducibility.
  • Interpretation and communication of behavioural insights.

Time permitted!

References

Andrews, M. (2021). Doing data science in R: An introduction for Social Scientists. SAGE Publications Ltd.

Tufte, E. R. (2001). The visual display of quantitative information (2nd ed.). Graphics Press.

van Lieburg, R., Sijyeniyo, E., Hartsuiker, R. J., & Bernolet, S. (2023). The development of abstract syntactic representations in beginning L2 learners of Dutch. Journal of Cultural Cognitive Science, 7, 289–309. https://doi.org/10.1007/s41809-023-00131-5

Wickham, H. (2016). ggplot2: Elegant graphics for data analysis. Springer.

Wickham, H., & Grolemund, G. (2016). R for data science: Import, tidy, transform, visualize, and model data. O’Reilly Media, Inc.