Data Visualization

Behavioral Data Science Toolbox 2026

Welcome to BDS Toolbox: Data Visualization

About these slides

Slides made using quarto

Cover photo made in R by Danielle Navarro

📌 Course website

data-visualization-2026

This is our central hub! Access slides, textbook, worksheets, assignments and other resources here.

💡 Tip: press S while viewing the slides to open the speaker notes.

Schedule

When Topic Preparation / Worksheets / Assignments
Session 1.
Tue 29/9, 15.00–18.00
GS.11
Fundamentals of DV Read: DV ch. 1; ch. 3
Worksheet: ggplot recap
Session 2.
Fri 2/10, 12.00–15.00
HvA
Exploratory viz Worksheet: ggplotly
Worksheet: working with AI, pt. 1
🚨 Sun 4/10, 23.59
Deadline Assignment 1 (individual) + Assignment 2, Part 1 (group)
Session 3.
Tue 6/10, 15.00–18.00
GS.11
Explanatory viz Worksheet: working with AI, pt. 2
Read: DV ch. 8
Session 4.
Fri 9/10, 12.00–15.00
HvA
Pitches & Q&A 🚨 Sun 11/10, 23.59
Deadline Assignment 2, Part 2 (group)

Friday sessions: time to work on group project!
Bring a (charged) laptop! 💻

Session 1 Tuesday, Sept. 29 Fundamentals of Data Visualization

Today

  • What is Data Visualization?
  • Why visualize data?
  • What makes a plot good (and bad)?
  • Guiding principles
  • Data Visualization Project

Data visualization = Data thinking

There are many skills involved in producing a good data visualization:

  • Technical (how to use particular tools)
  • Design (how to make visual representations that are engaging and appeal aesthetically)
  • Perception (how do certain notions of visual perception and cognition affect data communication)

Data visualization = Data thinking

Most important is to be able to derive reliable information from data using visual representations.

Data visualization = Data thinking

Your data visualization is effective only if it helps you, and your audience, understand the real world better

This requires data thinking skills:

  • Understanding of what the data represents (and what it doesn’t)
  • Transparency about the transformations and aggregations done to the data to produce the visualization
  • Awareness about how different visual representations affect the interpretation of the data, and an ability to justify which choice is most appropriate for your data and audience
  • Knowledge about the context from which the data is taken, and later presented.

Data visualization = Data thinking

Especially in our age of AI, these skills are invaluable

Why visualize data? 👀

💬 Discussion

Why visualize data?

Communicating with the public

…or boss, or stakeholder, or client

Why visualize data?

Anscombe’s quartet

Source: Same stats, different graphs Source: Wikipedia

Code
library("datasauRus")
library(scales)

datasaurus_dozen |>
  ggplot2::ggplot(aes(x = x, y = y, color = dataset)) +
  ggplot2::geom_point() +
  ggplot2::theme_void() +
  ggplot2::geom_smooth(
    method = "lm",
    color = "gray",
    fill = "gray",
    alpha = .5
  ) +
  ggplot2::theme(legend.position = "none", text = element_text(size = 30)) +
  ggplot2::facet_wrap(~dataset, ncol = 4)

💬 Discussion

What is more important? An eye or an algorithm?

What are the consequences of overrelying on statistical techniques?
What are the consequences of overrelying on visualizations?

Bad plots 💩

What makes a bad plot bad?

  • Aesthetic (ugly)

  • Perceptual (bad)

  • Substantive (wrong)

💬 Speed dates

  • What do you think about this plot?

  • What elements can be improved?

  • Are the problems aesthetic, perceptual, or substantive?

Ireland is headed straight for zero? 📉

💬 Speed dates

reddit.com/r/dataisugly

reddit.com/r/dataisugly
  • Misleading (or missing) information?
  • Many data visualizations might have a hidden agenda, due to e.g. marketing strategies.

💬 Speed dates

💬 Speed dates

Data to ink ratio

💬 Speed dates

💬 Speed dates

  • Do the colors make sense?

💬 Speed dates

Do the colors make sense?

Do the colors make sense?

💬 Speed dates

  • Are all elements needed?

💬 Speed dates

  • Are the axes correct?

💬 Speed dates

Is a zero-point needed?

Is a zero-point needed?

💬 Speed dates

  • Is it simple?

💬 Speed dates

⚠️ Stacked bar charts ⚠️

💬 Speed dates

⚠️ Pie charts ⚠️

💬 Speed dates

Visualizing proportions

  • Pie chart, stacked bar, or side-by-side bars?

https://clauswilke.com/dataviz/visualizing-proportions.html#

💬 Speed dates

Elementary Perceptual Tasks

Elementary Perceptual Tasks

💬 Speed dates

  • Does it support one conclusion?

💬 Speed dates

Storytelling with data - show just one conclusion!

Guiding principles 🪄

Tips for the best viz

  • Is it explaining data?

  • Is the information complete and correct?

  • Are axes correct? (+ Should they have a zero-point?)

  • Do the colors work? ( + Do they map to a relevant attribute?)

  • Are all elements needed?

  • What is the data to ink ratio?

  • Is it understandable & simple?

  • Does it portray one conclusion?

Some good examples

Distributions are informative

NYT Graphic - Obamacare spending

Making good plots: the BBC way

The BBC data journalism team makes its published graphics in R with ggplot, using their own package, bbplot.

➡️ BBC Visual and Data Journalism cookbook for R graphics

# devtools::install_github("bbc/bbplot")
library(bbplot)

my_plot <- ggplot(data, aes(x = year, y = value)) +
  geom_line(colour = "#1380A1", linewidth = 1) +
  bbc_style() # BBC house style

finalise_plot(
  plot_name = my_plot,
  source_name = "Source: ...",
  save_filepath = "my_plot.png"
)

Making good plots: the BBC way

Break

Code
library("RXKCD")
RXKCD::getXKCD(which = "833")

Data Visualization Project 📊

Assignment 📝

Assignment 1

Session 2 Friday, Oct. 2 Exploratory Data Visualization

Today

  • Exploratory data visualization
  • Brief introduction to interactive plots
  • Worksheet: ggplotly
  • Using AI for exploratory data viz
  • Worksheet: Working with AI, pt. 1
  • Work on your group assignment

💬 What makes exploration useful?

Illustration by Allison Horst

Illustration by Allison Horst

Exploratory versus explanatory

Source: Scott McCloud

Source: Scott McCloud
  • Exploratory: examine the structure of your data.
  • Explanatory: tell a story with your data.

Exploratory versus explanatory

Exploratory

Explanatory

Source: storytellingwithdata.com

Using data visualizations for exploration

  1. Understand your problem.
  2. Look at your data: head()
  3. What variables are available? What do they mean, what values do they take on?
  4. Identify your target variables.
  5. Now plot: their distributions, relationships with other variables, explore grouping structures, etc.
  6. What patterns do you see? Write them down, save the code.

Using data visualizations for exploration

Exploratory visualizations can be ugly

Use them to guide your understanding of the data, and inspire the final result you wish to present.

One variable → its distribution

Two variables + a group → relationships

Using data visualizations for exploration

Exploratory visualizations can also be beautiful

When the goal is to have the receiver explore and understand the data.

The Guardian: How coronavirus spreads ↗

SVT: Replay the 2026 Swedish election count ↗

Adding interactivity 🎮

💬 Why use interactive visualizations?

Adding interactivity 🎮

➡️ ggplotly()

  • Two main ways to creating a plotly object in R:

    1. Convert a ggplot2 object with ggplotly()
    2. Directly initialize a plotly object with plot_ly()

Adding interactivity 🎮

Additional functionality with plot_ly()

Adding interactivity 🎮

✅  Advantages ⚠️  Disadvantages
Explore data dynamically Harder to include in static formats (papers, print)
Zoom, pan, and hover for details Accessibility issues (screen readers, non colorblind-friendly defaults)
Reveal extra information without clutter Can overwhelm the audience if overused
Enhance engagement in presentations and reports Larger file sizes, slower rendering
Useful for exploratory analysis and dashboards Requires additional packages (e.g., {plotly})

Adding interactivity 🎮

Interactivity enhances, but does not replace, the fundamentals of good data visualization

Using AI for Data Exploration 🤖

💬 What about using AI for data exploration in visualization?

Using AI for Data Exploration 🤖

  1. AI lets you explore wider
    Use it for an efficient overview of the available data
  2. But, every plot hides decisions
    Ask the AI to list every transformation it made
  3. More plots = more chances of false positives
    Treat exploratory findings as a lead to continue checking, not a result
  4. You bring the meaning
    what does a variable measure? does the pattern make sense?
  5. Give the AI all the context you can
    e.g. codebooks, background information
  6. Evaluate, evaluate, evaluate!
    Before prompting, decide how you will verify the results yourself

Using AI for Data Exploration 🤖



Try it yourself!

Submitting Assignment 2, Part 1

  • The assignment is complete if:

    1. it contains multiple plots: show that you analysed your variable from at least 2 different perspectives.
    2. Has a theme and color-scheme. Although not necessary for exploratory viz, this gives me a chance to give feedback on your styling choices for Part 2.
    3. it highlights some interesting data points, for example using color or text. While this is also not necessary for exploratory viz, do this to show me the direction you will take your final visualization in, so I can give feedback.
    4. it contains a short description outlining your workflow: what exploration choices led to this visualization? did you use AI? if so, how and with which model? what did you learn about the data and how can you use this to inform the final, explanatory data visualization?
    5. your code runs, and the html can be downloaded and viewed on any laptop.
    6. your code is lintr-proof.

Now

In your groups:

AI worksheet, part 1. This should help set you up for your assignment. In 30 minutes we have a short discussion about your findings

Continue with Assignment 2, part 1.

Session 3 Tuesday, Oct. 6 Explanatory Data Visualization

Today

Better plots 🥇

  • General feedback assignments
  • Going from exploratory to explanatory
  • Advanced DV features
  • Using AI for explanatory DVs

Feedback on Assignment 2, Part 1

  • Use informative titles: state your conclusion in the title or subtitle in a declarative manner
  • Text: Increase font size, use bold-face in main statements
  • Visualize reliability: show sample size, confidence intervals, etc. Especially if using bins/groupings.
  • What is the added value of a boxplot?
  • Go from exploratory to explanatory!
    the audience should get the main conclusion without reading the description

Use point size to your advantage

Boxplots

Exploratory versus explanatory

Exploratory

Explanatory

Source: storytellingwithdata.com

Making an explanatory DV

  1. Start from your conclusion
  2. Adapt it to your audience
  3. Choose a chart type that fits the conclusion and the data
  4. Highlight your main conclusion

Step 1: Start from your conclusion

What is the main thing you learned from the data?

  • Pick one main statement.
  • Write down how you got there.
    Which inferential or modeling choices led to this conclusion?
  • Justify
    Why is this relevant, and why do you think it is correct?
    How confident are you in the validity, reliability, and robustness of the results?

Step 2: Adapt it to your audience

Formulate your conclusion so your audience understands it.

  • Who are they?
    Each research question has a target audience: a municipal officer, policymakers, newspaper readers, school boards…
  • Which details do they need?
    Pick the inferential/modeling details you want to show, and explain how they were derived.
  • Can they get it without reading your report?
    Use the title and labels to carry the message.

Step 2: Adapt it to your audience

Use your title and caption to do the explaining

  • Title: descriptive or declarative (state your conclusion!)
  • Methods: keep it brief, if needed at all
  • Results: only if not (fully) captured in the title
  • Definitions of colors, line types, error bars, etc.
  • Data source if external
  • Date and name for crediting

Source: datasketch.es

Step 2: Adapt it to your audience

Code
# lineplot = the original plot from Assignment 1
title_text <- paste(
  "LIB has the highest percentage of students reaching the target level,",
  "and Route8 the lowest. This gap holds even when accounting for the",
  "socio-economic status of schools."
)

caption_text <- paste0(
  "Data: DUO Open Onderwijsdata, doorstroomtoets results and reference ",
  "levels, school year 2024-2025;\n",
  "Inspectie van het Onderwijs, schoolweging 2024-2025.\n",
  "Chart: Annie Johansson | ",
  format(Sys.Date(), "%e %B %Y") |> str_trim()
)

legend_labels_oneline <- setNames(
  paste0(
    provider_n$provider,
    " (n = ", format(provider_n$n_pupils, big.mark = ",", trim = TRUE), ")"
  ),
  provider_n$provider
)

lineplot_titled <- lineplot +
  scale_color_manual(
    values = provider_colors,
    breaks = highlighted_providers, # legend in the same order as the lines
    labels = legend_labels_oneline,
    name = "Test provider"
  ) +
  scale_y_continuous(
    limits = c(0, 100),
    breaks = seq(0, 100, 25),
    labels = \(x) paste0(x, "%"),
    expand = expansion(mult = c(0, 0.02))
  ) +
  labs(
    title = str_wrap(title_text, width = 62),
    y = "Students reaching target level",
    caption = caption_text
  ) +
  theme(
    plot.title = element_text(
     face = "bold", size = 18, lineheight = 1.1,
     margin = margin(b = 12)
    ),
    plot.title.position = "plot",
    plot.caption = element_text(
      color = "grey40", size = 10, hjust = 0, lineheight = 1.2,
      margin = margin(t = 14)
    ),
    plot.caption.position = "plot",
    axis.title = element_text(color = "grey25", size = 13),
    axis.title.x = element_text(margin = margin(t = 8)),
    axis.title.y = element_text(margin = margin(r = 8)),
    axis.text = element_text(color = "grey35", size = 12),
    axis.line.x = element_line(color = "grey60", linewidth = 0.4),
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(color = "grey90", linewidth = 0.4),
    legend.justification = "left",
    legend.title = element_text(face = "bold", size = 12.5),
    legend.text = element_text(size = 12),
    legend.margin = margin(b = 0),
    plot.margin = margin(16, 20, 12, 16),
    plot.background = element_rect(fill = "white", color = NA)
  )

Step 3: Choose a chart type

One dataset, many visualizations

Code
data("pizzaplace")
pizza_top <- pizzaplace |>
  mutate(size = factor(size, levels = c("S", "M", "L"))) |>
  count(name, type, size, price, sort = TRUE) |>
  top_n(n = 5)
pizza_top |>
  gt() |>
  tab_header(title = "Pizza Top 5", subtitle = "2015") |>
  fmt_currency(columns = price, currency = "USD") |>
  tab_source_note(
    source_note = md(paste0(
      "Source: [pizzaplace dataset]",
      "(https://gt.rstudio.com/articles/gt-datasets.html#pizzaplace)"
    ))
  ) |>
  opt_stylize(style = 6)
Pizza Top 5
2015
name type size price n
big_meat classic S $12.00 1914
thai_ckn chicken L $20.75 1410
five_cheese veggie L $18.50 1409
four_cheese veggie L $17.95 1316
classic_dlx classic M $16.00 1181

Source: pizzaplace dataset

Code
pizza_top |>
  ggplot(aes(x = reorder(name, n, decreasing = TRUE), y = n)) +
  geom_point(aes(color = type, size = size)) +
  geom_text(aes(label = price), nudge_y = -30) +
  labs(title = "Pizza Top 5", subtitle = "2015", x = "name")

Step 3: Choose a chart type

One dataset, many visualizations

Code
pizza_season <- pizzaplace |>
  mutate(month = lubridate::month(date, label = TRUE)) |>
  group_by(month) |>
  count(type)

fig_season_1 <- pizza_season |>
  ggplot(aes(x = month, y = n, group = type)) +
  geom_bar(aes(fill = type), stat = "identity") +
  labs(
    title = "Pizza Season",
    subtitle = "2015",
    y = "Number of pizzas sold",
    x = "Month"
  )
fig_season_1

Code
fig_season_2 <- pizza_season |>
  ggplot(aes(x = month, y = n, group = type)) +
  geom_line(aes(linetype = type)) +
  labs(
    title = "Pizza Season",
    subtitle = "2015",
    y = "Number of pizzas sold",
    x = "Month"
  )
fig_season_2

Step 3: Choose a chart type

Step 3: Choose a chart type

Step 4: Highlight your main conclusion

  • Decide where you want the viewer to look first.
  • Use visual elements (colors, arrows, highlights) to guide that.

Step 4: Highlight your main conclusion

Advanced DV features

There are more advanced techniques available to you to make certain details, and your main point, clear to the audience.

  • Declutter remove what doesn’t add information
  • Themes, facets, layouts for structure and consistency
  • Color e.g., gray-scale with one accent color
  • Typography and annotation guide the eye to your conclusion
  • Uncertainty show how sure you are

Chart junk

NYT

NYT

Claus Wilke

Claus Wilke

NYT

NYT

Chart junk

You can try it yourself with geom_image() from ggimage

Code
library(ggimage)
# aggregate to totals
pizza_totals <- pizza_season |>
  group_by(type) |>
  summarise(total = sum(n), .groups = "drop") |>
  mutate(n_icons = round(total / 1000)) # 1 pizza = 1000 sales

# expand data: one row per pizza icon
# this is a trick so that each pizza icon can be plotted separately (essentially
# using geom_point but appearing as a bar)
chart_junk_data <- pizza_totals |>
  rowwise() |>
  mutate(icon_id = list(1:n_icons)) |>
  unnest(icon_id)

# plot with 🍕
pizza_plot <- ggplot(chart_junk_data, aes(x = icon_id, y = type)) +
  geom_image(aes(image = "images/pizza.png"), size = 0.2) +
  # add white rectangle to cover up excess icons (taken from pizza_totals data)
  geom_rect(
    data = pizza_totals,
    aes(
      xmin = total / 1000, xmax = total / 1000 + 2,
      ymin = as.numeric(factor(type)) - 0.5,
      ymax = as.numeric(factor(type)) + 0.5
    ),
    inherit.aes = FALSE,
    fill = "white"
  ) +
  labs(
    title = "Total Pizza Sales in 2015",
    x = "Sales (Scale 1:1000)",
    y = NULL
  ) +
  theme_minimal(base_size = 14) +
  theme(
    panel.grid.minor.y = element_blank(),
    panel.grid.major.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    axis.ticks = element_blank()
  )

pizza_plot

Themes

Code
fig_season_2 +
  theme_cowplot()

Code
my_theme <- theme_cowplot() +
  theme(
    panel.grid.major = element_line(color = "gray90"),
    axis.ticks = element_line(color = "gray20"),
    axis.text = element_text(color = "gray20", face = "italic", size = 16),
    axis.title = element_text(color = "gray20", face = "bold", size = 16),
    plot.title = element_text(hjust = 0.5, size = 20, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5, size = 18),
    legend.position = "top",
    legend.title = element_text(size = 16, face = "bold"),
    legend.text = element_text(size = 16)
  )
fig_season_2 + my_theme

Facets

  • theme_cowplot and theme_bw() format facets nicely.
  • Change facet format manually with theme(strip.text = element_text(...)) and theme(strip.background = element_rect(...)).
Code
fig_season_2 +
  facet_wrap(~type) +
  theme_bw(12) +
  theme(legend.position = "none")

Code
fig_season_2 +
  geom_line(linetype = "solid", color = "gray30", linewidth = 0.5) +
  facet_wrap(~type) +
  theme_minimal(12) +
  theme(
    legend.position = "none",
    strip.text = element_text(face = "bold", color = "plum4"),
    strip.background = element_rect(fill = "thistle2", color = NA)
  ) # fill for background; color for border

Combining plots: patchwork

  • Combine plots with +
  • Add a shared title, subtitle, and caption with plot_annotation()
  • Style them with plot_annotation(theme = theme(...))
Code
library(patchwork)
p1 <- ggplot(mtcars, aes(x = hp, y = mpg)) +
  geom_point(color = "steelblue", size = 3, alpha = 0.7) +
  theme_minimal() +
  labs(title = "Fuel efficiency vs Horsepower")

p2 <- ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
  geom_boxplot(fill = "steelblue", alpha = 0.7) +
  theme_minimal() +
  labs(title = "MPG by Number of Cylinders")

p1 + p2 +
  plot_annotation(
    title = "Analysis of mtcars dataset",
    caption = "Data source: mtcars",
    theme = theme(plot.title = element_text(face = "bold", size = 16))
  )

Color scales

Code
fig_quarter <- pizza_season |>
  mutate(quarter = case_when(
    month %in% c("Jan", "Feb", "Mar") ~ "Q1",
    month %in% c("Apr", "May", "Jun") ~ "Q2",
    month %in% c("Jul", "Aug", "Sep") ~ "Q3",
    month %in% c("Oct", "Nov", "Dec") ~ "Q4"
  )) |>
  ggplot(aes(x = quarter, y = n, group = type)) +
  geom_bar(aes(fill = type), stat = "identity", position = "dodge") +
  labs(title = "Pizza Season", y = "Number of pizzas sold", x = "")

fig_quarter +
  labs(subtitle = "Qualitative color scale") +
  scale_fill_brewer(type = "qual")

qualitative
categorical data

Code
fig_quarter +
  labs(subtitle = "Sequential color scale") +
  scale_fill_brewer(type = "seq")

sequential
ordered data, from low to high

Code
fig_quarter +
  labs(subtitle = "Diverging color scale") +
  scale_fill_brewer(type = "div")

diverging
ordered data with a critical midpoint, e.g. 0

Color blindness

Code
# colorblindr is installed from GitHub (clauswilke/colorblindr)
colorblindr::cvd_grid(fig_quarter)

The package MetBrewer has many colorblind-friendly palettes, e.g. scale_fill_manual(values = MetBrewer::met.brewer("VanGogh3", n = 4))

Typography

Change fonts with package showtext and function font_add_google(). Browse Google Fonts

Code
library(showtext)
sysfonts::font_add_google("Lekton")
showtext::showtext_auto()

fig_season_2 +
  theme_cowplot() +
  theme(text = element_text(family = "Lekton", size = 20))

Show uncertainty

How sure are you of your conclusion? Show it.

  • Sample size how many schools (or students) is each group based on?
  • Spread: is it informative to show the distribution, or error bars / intervals, not just the mean?
  • Missing data how did you handle them, and does it matter? If yes, add a note in the caption.
  • Confidence intervals (+ explain them in a way your audience understands.)

Putting it together

Consider your audience:

Code
pizza_plot

Putting it together

Consider your audience:

Code
sysfonts::font_add_google("Lobster")
sysfonts::font_add_google("Lexend")
showtext::showtext_auto()

pizza_plot +
  # add a geom_rect element with opacity on top of pizza bars, to highlight the
  # biggest bar
  geom_rect(
    data = pizza_totals |>
      mutate(highlight = ifelse(type == "classic", TRUE, FALSE)),
    aes(
      xmin = 0, xmax = total / 1000,
      ymin = as.numeric(factor(type)) - 0.5,
      ymax = as.numeric(factor(type)) + 0.5,
      alpha = highlight
    ),
    inherit.aes = FALSE,
    fill = "white"
  ) +
  scale_alpha_manual(values = c("TRUE" = 0, "FALSE" = 0.3), guide = "none") +
  labs(
    title = "The classic is a classic for a reason.",
    subtitle = "Total Pizza Sales in 2015",
    caption = "Source: pizzaplace dataset"
  ) +
  theme(
    text = element_text(family = "Lexend", color = "gray30"),
    plot.title = element_text(family = "Lobster", size = 20, color = "tomato3"),
    plot.subtitle = element_text(family = "Lexend", size = 16),
    axis.title.x = element_text(family = "Lobster", size = 16),
    axis.text.y = element_text(family = "Lobster", size = 16, color = "tomato3")
  )

Putting it together

Consider your audience:

Code
max_sales <- max(pizza_totals$total)
best_seller <- pizza_totals$type[pizza_totals$total == max_sales]

plot_data <- pizza_totals |>
  mutate(is_max = total == max_sales) |>
  mutate(type = forcats::fct_reorder(type, total, .desc = TRUE))

# the best seller is colored in the subtitle, like its bar (needs ggtext)
main_conclusion <- paste0(
  "The <span style='color:tomato3;'>", best_seller, " pizza</span> ",
  "is the clear leader with ", scales::comma(max_sales), " units sold."
)

ggplot(plot_data, aes(x = type, y = total, fill = is_max)) +
  geom_col(width = 0.7) +
  geom_text(
    aes(label = scales::comma(total)),
    vjust = -0.5,
    size = 4,
    fontface = "bold"
  ) +
  # highlight color for the best seller, neutral gray for the rest
  scale_fill_manual(
    values = c("TRUE" = "tomato3", "FALSE" = "grey70"),
    guide = "none"
  ) +
  labs(
    title = "Total Sales by Pizza Type",
    subtitle = main_conclusion,
    x = "Pizza Type",
    y = "Total Units Sold"
  ) +
  theme_cowplot() +
  theme(
    plot.title.position = "plot",
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = ggtext::element_markdown(size = 16, color = "grey30"),
    # the values are already on the bars, so the y-axis can go
    axis.line.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank(),
    axis.title.y = element_blank()
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

Final considerations

  • Are all visual elements necessary? (borders, gridlines, etc.)
  • Are names informative and adapted to the audience?
  • Is text big enough and legible at all plot sizes?
  • Can the plot render nicely on a presentation screen?

Some good examples 🏆

Some good examples 🏆

Continue learning

Get inspiration

Using AI for explanatory DVs 🤖

  1. Write your conclusion first, without AI
    The AI should help you show your conclusion, not choose it
  2. Let it do the technical work
    Annotations, highlighting, themes, layouts, color palettes
  3. Ask for alternatives
    3–4 different designs for the same message; then choose and justify
  4. Criticize everything it adds
    Does it make the conclusion clearer, or only decorate? Check the title for causal language
  5. Use it as a critic, carefully
    Ask for a skeptical review; you decide which critiques are valid
  6. Test with a naïve reader
    What do they conclude? Is that conclusion true?

Using AI for explanatory DVs 🤖



Try it yourself!

AI: Final note

Pitches: Friday, Oct. 9

Bring a first draft of your final visualization

Render it in an html or pdf file and upload it to Canvas. The draft is not graded, but the further along it is, the more useful the feedback. No slides needed!

  • 4-5 minutes pitch
    research question, approach, conclusion, open questions
  • 3-4 minutes discussion
    bring the questions you would like input on
  • AI use
    how did you use it, what did you learn, which obstacles or risks did you run into?

Handing in Assignment 2, Part 2

Deadline: Sunday, October 11th, 23:59

Hand in, on Canvas:

  1. The link to your group’s (public) GitHub repository, with all your code pushed
  • Your report, as:
    1. .Rmd
      with all code (lintr-proof!) to produce your final DV and report.
      (A quarto document as .qmd is also fine.)
    2. .html
      compiles only the final DV and report text.
      Hide your code by setting code_folding = TRUE in the preamble.
      make sure it knits correctly; we will not compile your .Rmd for you

And make sure I can clone your Github repo and completely reproduce your results.

Handing in Assignment 2, Part 2

Grading

Aesthetics 30% Clear and legible, no unnecessary clutter; color, labels and scales enhance readability
Communication 30% Can the main point be understood quickly, with minimal explanation?
Description 20% Research question, what you wanted to communicate, why this visualization, what you can conclude. AI statement
Creativity and Complexity 10% ex. Going beyond a default chart type, where it adds value without obscuring the message; adding consistent themes and styling matching the target audience / context.
Code Quality and Styling 10% Runs without errors, readable, lintr-proof

Final report formatting

You do not need to display all your code.

Hide or fold all code in your preamble:

---
title: "example rmd"
output:
  html_document:
    code_folding: hide
---

Or per code chunk:

```{r}
#| echo: false

# your code here
```

Now

In your groups:

  1. AI worksheet, part 2
  2. Continue with Assignment 2, part 2

Ask questions and consult me when needed!