Recreating a stacked barplot from the Pew Research Center in R with ggplot2 (CC350)
Pat uses R to show how to recreate a stacked bar plot posted by the Pew Research Center describing people’s sense of how different groups will fare under the Trump Administration. To pull this off he uses the ggplot2, showtext, and ggtext packages. The functions he uses from these packages include aes, coord_cartesian, element_blank, element_markdown, element_text, facet_grid, factor, font_add_google, geom_col, geom_text, ggplot, ggsave, labs, library, margin, mutate, pivot_longer, position_stack, rev, scale_fill_manual, showtext_auto, showtext_opts, theme, tribble, and unit. The newsletter describing this visualization at a 30,000 ft view can be found here. You can find the original Pew Research Center article here.
Code
library(tidyverse)
library(showtext)
library(ggtext)
font_add_google("Libre Franklin", "franklin")
font_add_google("Gelasio", "gelasio")
showtext_opts(dpi = 300)
showtext_auto()
data <- tribble(
~category,~gain,~none,~lose,~group,
"Total",21,37,41,"total",
"Men",24,42,34,"gender",
"Women",18,34,47,"gender",
"White",24,43,33,"race",
"Black",11,20,66,"race",
"Hispanic",17,29,52,"race",
"Asian*",15,38,47,"race",
"Ages 18-29",22,30,47,"age",
"30-49",22,34,42,"age",
"50-64",21,42,37,"age",
"65+",17,43,39,"age",
"Postgrad",17,38,45,"education",
"College grad",17,43,39,"education",
"Some college",22,33,43,"education",
"HS or less",23,37,40,"education",
"Rep/Lean Rep",35,51,13,"politics",
"<span style='color:gray50'>Conserv</span>",39,54,6,"politics",
"<span style='color:gray50'>Mod/Lib</span>",29,47,23,"politics",
"Dem/Lean Dem",7,23,69,"politics",
"<span style='color:gray50'>Cons/Mod</span>",8,25,66,"politics",
"<span style='color:gray50'>Liberal</span>",6,20,74,"politics"
) %>%
mutate(group = factor(group,
levels = c("total", "gender", "race",
"age", "education", "politics")),
category = factor(category, levels = rev(category)))
data %>%
pivot_longer(-c(category, group),
names_to = "effect", values_to = "percent") %>%
mutate(effect = factor(effect, levels = c("lose", "none", "gain"))) %>%
ggplot(aes(x = percent, y = category, fill = effect, label = percent)) +
geom_col(width = 0.7) +
geom_text(position = position_stack(vjust = 0.5),
family = "franklin", size = 6, size.unit = "pt") +
facet_grid(group~., scales = "free_y", space = "free_y") +
coord_cartesian(expand = FALSE, clip = "off") +
scale_fill_manual(
name = NULL,
breaks = c("gain", "none", "lose"),
values = c("#D0A62D", "#DBD9C6", "#E3CA83"),
labels = c("Gain influence", "Not be affected", "Lose influence")
) +
labs(
title = "How Americans feel people like them<br>will fare under the Trump administration",
subtitle = "*% who say **people like yourself** will in<br>Washington with Donald Trump taking office*",
caption = "\\* Estimates for Asian adults are representative of English speakers<br>only.<br>Note: No answer responses are not shown.<br>Source: Survey of U.S. adults conducted Jan. 27-Feb. 2, 2025.<br><br>**<span style='color:black'>PEW RESEARCH CENTER</span>**",
x = NULL,
y = NULL
) +
theme(
text = element_text(family = "franklin"),
legend.position = "top",
legend.justification.top = "right",
legend.text = element_text(size = 6, margin = margin(l = 2)),
legend.key.size = unit(5, "pt"),
legend.key.spacing.x = unit(2, "pt"),
legend.box.spacing = unit(8, "pt"),
legend.margin = margin(r = 0),
panel.grid = element_blank(),
panel.background = element_blank(),
strip.text = element_blank(),
axis.ticks = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_markdown(size = 6, color = "black"),
plot.title.position = "plot",
plot.title = element_markdown(face = "bold", size = 9,
lineheight = 1.4),
plot.subtitle = element_markdown(family = "gelasio", size = 8,
color = "gray40", lineheight = 1.2,
margin = margin(b = 8)),
plot.caption.position = "plot",
plot.caption = element_markdown(hjust = 0, size = 5.5, lineheight = 1.4,
color = "gray40",
margin = margin(t = 16)),
plot.margin = margin(t = 10, r = 8, b = 10, l = 3),
panel.spacing.y = unit(15, "pt")
)
ggsave("gainers_losers.png", width = 2.53, height = 6)