Tidy Tuesday: Tuskegee Airmen

By Katie Press in TidyTuesday

February 13, 2022

knitr::opts_chunk$set(echo = TRUE,message=FALSE,warning=FALSE)
library(tidyverse)
library(usmap)
library(emojifont)
library(showtext)

Data

I geocoded as many of the records as I could - some of the hometowns and/or states were incorrect and had to be cleaned up. I uploaded this file to Kaggle as well.

airmen <- readRDS("/Users/katiepress/Desktop/Rproj/Tuskeegee/airmen.RDS")

Colors and Fonts for Styling the Map

cadet.light <- "#386F81"
blood.red <- "#780e0d"
alabaster <- "#F2F0E3"
field.drab <- "#645B40"
cadet <- "#4d6673"
medal.yellow <-  "#E3A95D"
gunmetal <- "#172a33"

font_add_google(name = "Yesteryear", family = "yesteryear")
font_add_google(name = "Dynalight", family = "dynalight")
font_add(family = "chuterolk", regular = "./Users/katiepress/Downloads/ChuterolkFreeRegular-L3R55.ttf")

Count of Airmen per Hometown and State

This information will be used for the state colors and the point overlays. I’m also adding the fontawesome icon I want to use instead of points for my cities. This can be done using the emojifont package, and I’m storing that in a column called “label”.

city_counts <- count(airmen, new_city, new_state, "lon" = longitude, 
                     "lat" = latitude) %>% 
  filter(!is.na(lon)) %>% 
  select(lon, lat , everything())

city_counts <- city_counts %>% 
  filter(!new_state %in% c("HT", "HAITI", "UNK", "VI"))

city_counts <- city_counts %>% 
  arrange(desc(lon)) %>% 
  slice(8:362)

city_counts <- city_counts %>% 
  mutate(label = fontawesome('fa-fighter-jet'))

city_counts <- city_counts %>% 
  mutate(count_group = factor(case_when(n < 6 ~ "1-5",
                                 between(n, 6, 10) ~ "6-10",
                                 between(n, 11, 20) ~ "11-20",
                                 n > 20 ~ "20+"), levels = c("1-5", "6-10", "11-20", "20+"))) 

city_counts <- city_counts %>% filter(new_state != "TD")

cities_t <- usmap_transform(city_counts)

state_counts <- count(airmen %>% filter(new_state %in% state.abb), new_state)


state_counts <- state_counts %>% 
  mutate(count_group = factor(case_when(n <11 ~ "1-10",
                                 between(n, 11, 25) ~ "11-25",
                                 between(n, 26, 50) ~ "26-50",
                                 n > 50 ~ "50+"), 
                              levels = c("1-10", "11-25", "26-50", "50+")))

Creating the Map

I’m using the usmap package for the base plot, which is actually a ggplot2 format I believe, just a shortcut way of doing things. First, get some map info and join the state counts from earlier. Important note here - apparently to use this information in your map, you can only have two columns and one of them has to be a fips code or state.

usa_map <- usmap::us_map(regions = "states") %>% 
  left_join(state_counts %>% select("abbr" =  new_state, count_group)) %>% 
  select(fips, count_group)

Now plot the base map, excluding Alaska and Hawaii since there are no airmen from those states anyways. I’m adding a geom_text layer here with a fontawesome icon of a fighter jet - this is from the emojifont package. Here I’m assigning colors to the states based on a discrete variable, which is not usually best practice for count data. However, I’m going for a certain style here that is inspired by WEB DuBois maps:

DuBois Maps

I was also inspired by this vintage-style poster

Squadron Poster

The size of the fighter jet icon will also correspond to the number of airmen from that particular city. I was having a terrible time trying to format the legend for this, until I realized that I had the label inside the aesthetic. As soon as I took it out everything worked perfectly.

state_map <- plot_usmap(
    regions = "state",
    exclude = c("Alaska", "Hawaii"),
    data = usa_map,
    values = "count_group"
  ) +
  geom_text(
    data = cities_t,
    aes(x = lon.1, y = lat.1, size = count_group),
    label = fontawesome('fa-fighter-jet'),
    color = alabaster,
    family = 'fontawesome-webfont'
  )  +
  scale_fill_manual(
    name = "Airmen per State",
    values = c(field.drab, "#203A46", blood.red, medal.yellow),
    na.value = "#DADABE"
  ) +
  scale_size_manual(name = "Airmen per Hometown", values = c(5, 7, 9, 11)) +
  labs(
    title = "The",
    subtitle = "TUSKEGEE AIRMEN",
    caption = str_c("Red Tails 1941-1949")
  )

Finalize the Map

It took a lot of code to format since I used several different fonts and I’m pretty picky about how my visualizations look in general. I was pretty satisfied with the result, EXCEPT for the fact that I could not get it to look the same when I tried printing it inline in this Rmarkdown document, or saving with ggsave(). This is one of the things that annoys me about ggplot. In any case, I was able to save the PNG to my desktop and I will leave the code here and just upload the photo of the chart. If you want to print it out inline, I’ve used fig.height=6, fig.width=6, dev=‘png’, dpi=300 in the setup for this chunk.

plot +
  guides(
    size = guide_legend(title.position = "top", title.hjust = .5),
    fill = guide_legend(title.position = "top", title.hjust = .5)
  ) +
  theme(
    legend.position = "bottom",
    legend.text = element_text(
      family = "chuterolk",
      size = 28,
      color = alabaster
    ),
    legend.title = element_text(
      family = "chuterolk",
      size = 32,
      color = alabaster
    ),
    legend.background = element_rect(fill = cadet.light, color = cadet.light),
    panel.background = element_rect(fill = cadet.light, color = cadet.light),
    legend.key = element_rect(fill = NA),
    plot.background = element_rect(fill = cadet.light, color = cadet.light),
    plot.title = element_text(
      family = "dynalight",
      color = alabaster,
      size = 40,
      hjust = .4,
      vjust = -0.1
    ),
    plot.subtitle = element_text(
      family = "chuterolk",
      color = alabaster,
      size = 60,
      hjust = .5
    ),
    plot.caption = element_text(
      family = "yesteryear",
      color = blood.red,
      size = 40,
      vjust = 54,
      hjust = .5
    ),
    legend.key.size = unit(1, 'cm'),
    legend.spacing = unit(2.2, 'inches'),
    legend.margin = margin(0, 0, 0, 20)
  )
Tuskegee Airmen Final Map
Posted on:
February 13, 2022
Length:
4 minute read, 842 words
Categories:
TidyTuesday
Tags:
Maps
See Also:
Tidy Tuesday: Drought Conditions
comments powered by Disqus