---
layout: post
title: "Using ggplot2 to recreate a visual of perceptions of Trump's policies in LA from (CC362)"
blurb: "Wait until you see how I made those points!"
author: "PD Schloss"
date: 2025-07-09 8:00
comments: false
youtube: V0MdYRejiyg
start_hash: 
end_hash: 
---

Pat recreates a faceted waffle chart from the Washington Post to show the responses to a survey asking people's sentiments about the use of military to quell the LA protests using ggplot2. The plot was generated using functions from the tidyverse including the dplyr, ggplot2, ggimage, showtext, ggtext, and glue packages. The functions he uses from these packages include aes, ceiling, coord_cartesian, element_blank, element_markdown, element_textbox_simple, facet_wrap, factor, filter, font_add_google, function, geom_image, geom_jitter, ggplot, ggsave, glue, labs, library, map, margin, mutate, position_jitter, rep, round, scale_color_manual, scale_y_continuous, scale_y_reverse, seq, showtext_auto, showtext_opts, sum, theme, tibble, tribble, unit, and unnest. The newsletter describing this visualization at a 30,000 ft view can be [found here](https://shop.riffomonas.org/posts/pseudo-waffle-plots-from-la-from-the-washington-post). You can find the original article describing the ridgeline plot [here](https://archive.is/uQlY2). 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)
library(ggtext)
library(glue)
library(ggimage)

font_add_google("Libre Franklin", "franklin")
font_add_google("Playfair Display", "playfair")
showtext_opts(dpi = 300)
showtext_auto()

waffle_coordinates <- function(n, n_cols = 18){
  
  n_rows <- ceiling(n / n_cols)
  n_extras <- n - n_cols * (n_rows - 1)
  
  row_indices <- c(rep(1:(n_rows - 1), each = n_cols),
                   rep(n_rows, n_extras))

  start_extras <- (n_cols - n_extras) / 2 + 1
  end_extras <- start_extras + n_extras - 1
  
  col_indices <- c(rep(1:n_cols, times = n_rows - 1), 
                   seq(start_extras, end_extras, 1))
                   
  tibble(x = rep(col_indices, 3),
         y = rep(row_indices, 3))
}


data <- tribble(
  ~category, ~level, ~logo,
  "support",  23 * 18 + 7, "wp_logo.png",
  "unsure",   8 * 18 + 5, NA,
  "oppose",   24 * 18 + 13, NA
) %>%
  mutate(
    percent = round(100 * level / sum(level), digits = 0),
    label = glue("**{str_to_sentence(category)}**<br>{percent}%"),
    label = factor(label, levels = label))


data %>%
  mutate(positions = map(level, waffle_coordinates)) %>%
  unnest(positions) %>%
  ggplot(aes(x = x, y = y)) +
  geom_jitter(aes(color = category), show.legend = FALSE,
              position = position_jitter(width = 0.1, height = 0.1,
                                         seed = 19760620)) +
  geom_image(data = filter(data, category == "support"),
             x = -1, y = 7.5, aes(image = logo), size = 0.12) +
  facet_wrap(~label, nrow = 1) +
  scale_color_manual(
    breaks = c("support", "unsure", "oppose"),
    values = c("#4A8F9B", "#A8A8A8", "#E6823D")
  ) +
  scale_y_reverse() +
# scale_y_continuous(transform = "reverse") +
  coord_cartesian(expand = FALSE, clip = "off",
                  xlim = c(0.5, 18.5),
                  ylim = c(25.5, 0.5)
                  ) +
  labs(
    title = "Do you support or oppose Trump sending the National Guard and
             Marines to respond to the L.A. protests?"
  ) +
  theme(
    plot.margin = margin(t = 5, r = 10, b = 5, l = 20),
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_blank(),
    panel.background = element_blank(),
    strip.background = element_blank(),
    panel.spacing.x = unit(10, "pt"),
    strip.text = element_markdown(family = "franklin", lineheight = 1.3),
    plot.title = element_textbox_simple(family = "playfair", face = "bold",
                                        linetype = 1, linewidth = 0.25,
                                        padding = margin(8, 8, 8, 10),
                                        margin = margin(3, 0, 20, 0),
                                        r = unit(15, "pt"), size = 19,
                                        lineheight = 1.3,
                                        width = 0.93, hjust = 0)
  )

ggsave("la_waffle_plot.png", width = 6, height = 4.435)
```
