Week 13: Visualize

[13a] Positions

Topics

  • Create multiple subplots using facet_wrap() and facet_grid()
  • Use position adjustments to stack, fill, and dodge bar charts
  • Address overplotting in scatterplots using jittering and hex-binning

Readings

Slides

*Note that you can click the three-line (hamburger) icon on the bottom-left of the slides to access a navigation menu. You can click inside the slides region and press the left and right arrow keys on your keyboard to advance and reverse the slides and animations.

Practice

1) Faceting Sleep Patterns

Using the msleep dataset (from {ggplot2}), let’s explore how different types of “vores” (carnivores, herbivores, etc.) sleep.

  • Create a scatterplot with bodywt on the x-axis and sleep_total on the y-axis.
  • Use facet_wrap() to create subplots based on the vore column.
  • Because mammals have very different weight ranges, set scales = "free_x" within the facet function so each subplot has its own x-axis scale.

Answer key

library(tidyverse)

data("msleep", package = "ggplot2")

# We drop NAs in vore to keep the facets clean
msleep |> 
  drop_na(vore) |> 
  ggplot(aes(x = bodywt, y = sleep_total)) +
  geom_point() +
  facet_wrap(facets = vars(vore), scales = "free_x")

2) Comparing Metro Areas Across States

Let’s use the midwest dataset (from {ggplot2}) to see the distribution of counties that are considered “metropolitan” across different states.

  • Create a bar chart (geom_bar) with state on the x-axis.
  • Map the fill aesthetic to inmetro (using factor() to treat it as categorical).
  • Use position = "fill" to show the proportion (rather than the count) of metro vs. non-metro counties in each state.
  • Update the y label to “proportion” and the fill label to “Is Metro?”

Answer key

data("midwest", package = "ggplot2")

ggplot(midwest, aes(x = state, fill = factor(inmetro))) +
  geom_bar(position = "fill") +
  labs(y = "proportion", fill = "Is Metro?")

3) Handling Overlapping Geyser Data

The faithful dataset (from {datasets}) contains many overlapping points. Let’s practice two different ways to make the data density clearer.

  • First, create a standard scatterplot of eruptions (x) vs waiting (y).
  • Create a second version of the plot that uses jittering and alpha-transparency to reveal hidden points.
  • Create a third version using geom_hex() to bin the points into count-based shapes. Note: You will need the {hexbin} library installed.

Answer key

library(hexbin)

data("faithful", package = "datasets")

# Version 1: Jittering
ggplot(faithful, aes(x = eruptions, y = waiting)) +
  geom_point(position = "jitter", alpha = 0.5)


# Version 2: Hex Binning
ggplot(faithful, aes(x = eruptions, y = waiting)) +
  geom_hex()

[13b] Maps

Topics

  • Extract and draw polygon map data in ggplot2
  • Add points and text labels to existing maps
  • Join data with map data and make complex maps

Files

Readings

  • EGDA (3E) Chapter 6: Maps

Slides

*Note that you can click the three-line (hamburger) icon on the bottom-left of the slides to access a navigation menu. You can click inside the slides region and press the left and right arrow keys on your keyboard to advance and reverse the slides and animations.

Practice

1) Mapping the World

Let’s practice drawing a map of the entire world using the {maps} package.

  • Extract the coordinates for the world map using map_data("world") and convert it to a tibble.
  • Create a ggplot mapping the long (x), lat (y), and group aesthetics.
  • Add the map polygons using geom_polygon(), setting the fill to “lightgreen” and the outline color to “black”.
  • Apply coord_quickmap() to fix the geographic distortion.

Answer key

library(tidyverse)
library(maps)
## 
## Attaching package: 'maps'
## The following object is masked from 'package:purrr':
## 
##     map

# Extract the world map data
world_map <- map_data("world")

# Draw the map
ggplot(world_map, aes(x = long, y = lat, group = group)) +
  geom_polygon(fill = "lightgreen", color = "black") +
  coord_quickmap()

2) Pinpointing Global Cities

Now let’s add some points to our world map to represent major global cities.

  • Run the provided code to create a small dataset of three cities.
  • Start with your world map code from the previous question, but move the mapping aesthetics into the geom_polygon() layer so they do not conflict with the points.
  • Add a geom_point() layer using the new cities dataset.
  • Map long to x and lat to y for the points, and set their color to “red” with a size of 3.
cities <- tribble(
  ~city, ~long, ~lat,
  "Tokyo", 139.6917, 35.6895,
  "London", -0.1276, 51.5072,
  "New York", -74.0060, 40.7128
)

Answer key

ggplot() +
  geom_polygon(
    data = world_map, 
    mapping = aes(x = long, y = lat, group = group),
    fill = "lightgreen", 
    color = "black"
  ) +
  geom_point(
    data = cities,
    mapping = aes(x = long, y = lat),
    color = "red", 
    size = 3
  ) +
  coord_quickmap()

3) Creating a Global Choropleth

Let’s visualize some simulated statistical data across different countries to create a choropleth map.

  • Run the provided code to load a small dataset of arbitrary values for five countries.
  • Join the world_map dataset with country_data using a left_join(). Match them by the “region” column.
  • Create a map using geom_polygon() where the fill aesthetic is mapped to the new value column.
  • Set the polygon outline color to “black” with a linewidth of 0.3.
  • Keep coord_quickmap() to maintain the correct proportions.
country_data <- tribble(
  ~region, ~value,
  "Canada", 10,
  "Brazil", 25,
  "Australia", 40,
  "China", 80,
  "Algeria", 15
)

Answer key

# Join the data
world_joined <- world_map |> 
  left_join(country_data, by = "region")

# Draw the choropleth
ggplot(world_joined, aes(x = long, y = lat, group = group)) +
  geom_polygon(aes(fill = value), color = "black", linewidth = 0.3) +
  coord_quickmap()

[13c] Themes

Topics

  • Apply complete themes to rapidly change the look of plots
  • Customize individual theme elements for fine-grained control
  • Combine multiple plots into complex layouts using patchwork

Readings

  • R4DS (2E) Section 11.5: Themes
  • R4DS (2E) Section 11.6: Layout

Slides

*Note that you can click the three-line (hamburger) icon on the bottom-left of the slides to access a navigation menu. You can click inside the slides region and press the left and right arrow keys on your keyboard to advance and reverse the slides and animations.

Practice

1) Applying Complete Themes and Moving Legends

Let’s practice applying a built-in theme and adjusting the legend position for a cleaner look.

  • Run the provided code to create a base plot p_base using the mpg dataset.
  • Apply the theme_minimal() complete theme to p_base.
  • Use the theme() function to move the legend to the “bottom” of the plot.
library(tidyverse)

p_base <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(size = 3) +
  labs(title = "Engine Size vs. Highway MPG")

Answer key

p_base +
  theme_minimal() +
  theme(legend.position = "bottom")

2) Customizing Theme Elements

Complete themes are great, but sometimes you need fine-grained control over specific components like text formatting and gridlines.

  • Start with the p_base plot from the previous question.
  • Use theme() and element_text() to make the plot title bold (face = "bold").
  • Use element_blank() to completely remove the minor gridlines (panel.grid.minor).
  • Use element_line() to make the major gridlines (panel.grid.major) dashed.

Answer key

p_base +
  theme(
    plot.title = element_text(face = "bold"),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(linetype = "dashed")
  )

3) Combining Plots with Patchwork

When presenting data, you often need to combine multiple related subfigures into one cohesive layout.

  • Run the provided code to create three simple plots (p1, p2, p3) and load the patchwork library.
  • Use patchwork operators to place p1 and p2 side-by-side on the top row, and place p3 below them. Use parentheses to group the top row.
  • Add an overall plot_annotation() with the title “Vehicle Exploration” and automatically tag the subfigures using tag_levels = "A".
library(patchwork)

p1 <- ggplot(mpg, aes(x = class)) + 
  geom_bar(fill = "steelblue")

p2 <- ggplot(mpg, aes(x = drv)) + 
  geom_bar(fill = "seagreen")

p3 <- ggplot(mpg, aes(x = displ, y = hwy)) + 
  geom_point(alpha = 0.5)

Answer key

(p1 | p2) / p3 +
  plot_annotation(
    title = "Vehicle Exploration",
    tag_levels = "A"
  )