---
layout: post
title: "Using R's ggplot2 to recreate WEB DuBois's Panel 12 from the 1900 Paris Exposition (CC340)"
blurb: "Recreating an area plot"
author: "PD Schloss"
date: 2025-02-10 8:00
comments: false
youtube: 5TGjhKson_s
start_hash: 
end_hash: 
---

Pat recreates an iconic figure that WEB DuBois presented at the 1900 Paris Exposition showing the change in the percentage of Blacks who were free in Georgia between 1790 and 1870 using tools from R's ggplot2, dplyr, and showtext. The functions he uses from these packages include aes, annotate, arrange, as.character, coord_cartesian, element_blank, element_line, element_rect, element_text, factor, fill, font_add, full_join, geom_area, geom_hline, geom_path, geom_text, ggplot, ggsave, if_else, labs, lead, length, library, margin, mutate, paste0, pivot_longer, runif, scale_fill_manual, scale_x_continuous, scale_y_continuous, select, seq, showtext_auto, showtext_opts, theme, tibble, and tribble. Pat's newsletter describing how he would go about generating the figure can be [found here](https://shop.riffomonas.org/posts/remaking-classic-hand-drawn-data-visualizations-from-1900). The book Pat mentions by Whitney Battle-Baptiste and Britt Rusert, titled "W.E.B. Du Bois's Data Portraits: Visualizing Black America" is [available here](https://amzn.to/4heJOWZ). A great set of talks about the DuBois data portraits is [available on YouTube](https://www.youtube.com/watch?v=ZZST1AZj-dQ&ab_channel=Tableau). The Anthony Starks GitHub repository can be [found here](https://github.com/ajstarks/dubois-data-portraits/). If you have a figure that you would like to see me discuss in a future newsletter and episode of Code Club, email me at pat@riffomonas.org!

<iframe style="margin: 0 auto;display:block;" width="560" height="315" src="https://www.youtube.com/embed/{{ page.youtube }}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## Code

```R
library(tidyverse)
library(showtext)
#Icons made from <a href="https://www.onlinewebfonts.com/icon">svg icons</a>is licensed by CC BY 4.0</div>

font_add("b52", regular = "OnlineWebFonts_COM_5d6bfe4f38a46ad2c2304bc1f8ea8151/B52-ULC W00 ULC/B52-ULC W00 ULC.ttf")
font_add("vasarely", regular = "vasarely-light.otf")
showtext_auto()
showtext_opts(dpi = 300)


ragged_line <- tibble(year = seq(1790, 1870, 0.5),
                      max = runif(length(year), min = 2.95, max = 3.05))

slave_free <- tribble(
  ~year, ~slave, ~free,
  1790,    98.7,   1.3,
  1800,    98.3,   1.7,
  1810,    98.3,   1.7,
  1820,    98.8,   1.2,
  1830,    99.2,   0.8,
  1840,    99.1,   0.9,
  1850,    99.3,   0.7,
  1860,    99.2,   0.8,
  1870,     0.0, 10) %>%#100.0 ) %>% # adjusted to 10 to highlight slope of line
  
  mutate(pretty_free = if_else(year == 1790 | year == 1870,
                               paste0(free, "%"),
                               as.character(free)))


top_line <- slave_free %>%
  mutate(free_start = free,
         free_next = lead(free),
         free_slope = (free_next - free_start) / 10) %>%
  full_join(ragged_line, by = "year") %>%
  arrange(year) %>% 
  fill(free_start, free_slope) %>%
  mutate(free = free_start + free_slope * (year %% 10),
         free = if_else(free > max, max, free),
         slave = max - free
         ) %>%
  select(year, free, slave) %>%
  pivot_longer(-year, names_to = "status", values_to = "percent") %>%
  mutate(status = factor(status, levels = c("slave", "free")))


top_line %>%
  ggplot(aes(y = year, x = percent, fill = status)) +
  geom_area(color = "white", orientation = "y",
            linewidth = 0.25, show.legend = FALSE) +
  geom_hline(yintercept = seq(1790, 1870, 10), color = "white",
             linewidth = 0.25) +
  geom_path(data = ragged_line,
            aes(y = year, x = max),
            inherit.aes = FALSE, color = "black", linewidth = 0.25) +
  geom_text(data = slave_free,
            aes(x = -0.4, y = year, label = pretty_free),
            inherit.aes = FALSE, family = "vasarely", hjust = 0,
            size = 8, size.unit = "pt") +
  annotate(geom = "text", x = -0.5, y = 1786,
           label = "PERCENT\nOF\nFREE NEGROES",
           lineheight = 0.8, family = "vasarely", size = 5, size.unit = "pt") +
  labs(title = "SLAVES AND FREE NEGROES.",
       x = NULL,
       y = NULL) +
  scale_fill_manual(breaks = c("free", "slave"),
                    values = c("#dc143c", "#000000")) +
  scale_x_continuous(transform = "reverse",
                     position = "top",
                     labels = c("", "1%", "2%", "3%")) +
  scale_y_continuous(transform = "reverse",
                     breaks = seq(1790, 1870, 10)) +
  coord_cartesian(xlim = c(3.1, 0), ylim = c(1870, 1790),
                  expand = FALSE, clip = "off") +
  theme(
    text = element_text(family = "vasarely"),
    plot.title = element_text(family = "b52", hjust = 0.5, size = 12,
                              margin = margin(t = 0, b = 20)),
    plot.margin = margin(t = 20, l = 90, r = 110, b = 70),
    axis.ticks.x = element_line(linewidth = 0.25),
    axis.text.x = element_text(size = 6),
    axis.text.y = element_text(margin = margin(r = 10)),
    axis.ticks.y = element_blank(),
    panel.background = element_rect(fill = "white"),
    panel.grid = element_blank()
  )

# actually 22x28 inches
ggsave("panel_12.png", width = 5, height = 6.24, unit = "in")
```
