Skip to content

Instantly share code, notes, and snippets.

@ryanburge
Created May 27, 2025 19:22
Show Gist options
  • Select an option

  • Save ryanburge/f98d623642477983397f7a7cf75ae9de to your computer and use it in GitHub Desktop.

Select an option

Save ryanburge/f98d623642477983397f7a7cf75ae9de to your computer and use it in GitHub Desktop.
# Define the common pattern as a function to DRY
ab_summary <- function(df, var, label) {
df %>%
mutate(ab = case_when({{ var }} == 1 ~ 1,
{{ var }} == 2 ~ 0)) %>%
group_by(year) %>%
mean_ci(ab, wt = weight, ci = 0.84) %>%
mutate(type = label)
}
# Generate each summary
ab_all <- ab_summary(cces, ab_choice, "Any Reason")
ab_rape <- ab_summary(cces, ab_rape, "Only In Cases of Rape,\nIncest, Life of Mother")
ab_late <- ab_summary(cces, ab_late, "Ban After 20 Weeks")
ab_ins <- ab_summary(cces, ab_ins, "Employers Insurance Can\nDecline Abortion Coverage")
ab_funds <- ab_summary(cces, ab_funds, "No Federal Funds for Abortion")
ab_never <- ab_summary(cces, ab_never, "Illegal in All Circumstances")
# Combine all
ab_combined <- bind_rows(ab_all, ab_rape, ab_late, ab_ins, ab_funds, ab_never) %>% na.omit()
ab_labels <- ab_combined %>%
group_by(type) %>%
filter(year == min(year) | year == max(year)) %>%
mutate(label = scales::percent(mean, accuracy = 1))
# Facet line plot
ab_combined %>%
ggplot(., aes(x = year, y = mean, color = type)) +
geom_line() +
geom_point(stroke = 1 , shape = 21, fill = "white") +
facet_wrap(~ type) +
scale_color_manual(values = c("#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02")) +
scale_x_continuous(limits = c(2013, 2025), breaks = c(2014, 2016, 2018, 2020, 2022, 2024)) +
scale_y_continuous(labels = percent, limits = c(0, .8)) +
theme_rb() +
geom_text(data = ab_labels,
aes(label = label),
vjust = -0.5,
size = 5,
show.legend = FALSE, family = "font", color = "black") +
theme(strip.text = element_text(size = 14)) +
labs(x = "", y = "Share Agreeing", title = "Changes in Abortion Opinion, 2014-2024", caption = "@ryanburge\nData: Cooperative Election Study, 2024")
save("abortion_over_time24.png")
# Define the common pattern as a function to DRY
ab_summary <- function(df, var, label) {
df %>%
filter(year == 2016 | year == 2024) %>%
mutate(ab = case_when({{ var }} == 1 ~ 1,
{{ var }} == 2 ~ 0)) %>%
group_by(year, trad2) %>%
mean_ci(ab, wt = weight, ci = 0.84) %>%
mutate(type = label)
}
# Generate each summary
ab_all <- ab_summary(cces, ab_choice, "Any Reason")
ab_never <- ab_summary(cces, ab_never, "Complete Ban")
# Combine all
both <- bind_rows(ab_all, ab_never) %>% na.omit()
# Filter for 2014 and 2024 only
ab_compare <- both %>%
filter(year %in% c(2016, 2024)) %>%
mutate(
year = factor(year),
trad2 = fct_reorder2(trad2, year, mean) # orders within each type
)
# Plot
ggplot(ab_compare, aes(x = mean, y = trad2, fill = year)) +
geom_col(position = position_dodge(width = 0.7), width = 0.65, color = "black") +
facet_wrap(~ type, ncol = 1) +
x_pct() +
scale_fill_manual(values = c("2016" = "#7570b3", "2024" = "#d95f02")) +
labs(
title = "Changes in Abortion Opinion by Religion (2016 vs 2024)",
x = "Share Agreeing",
y = NULL,
fill = "Year",
caption = "@ryanburge | Data: Cooperative Election Study"
) +
theme_rb() +
theme(strip.text = element_text(size = 14))
library(ggalt) # for geom_dumbbell
# Prepare data for dumbbell plot
gap <- ab_compare %>%
filter(year %in% c(2016, 2024)) %>%
select(year, trad2, mean, type) %>%
pivot_wider(names_from = year, values_from = mean) %>%
mutate(
diff = round((`2024` - `2016`) * 100),
label = paste0(ifelse(diff > 0, "+", ""), diff, " pts."),
trad2 = fct_reorder(trad2, `2024`) # sort by most recent value
)
# Dumbbell plot
ggplot(gap, aes(x = `2016`, xend = `2024`, y = fct_rev(trad2))) +
geom_dumbbell(
color = "gray80",
stroke = 1.5,
shape = 21,
size = 0.8,
colour_x = "#7570b3", # 2016
colour_xend = "#d95f02" # 2024
) +
geom_text(
aes(x = (`2016` + `2024`) / 2, label = label),
vjust = -0.6, size = 3.5, color = "black", family = "font"
) +
scale_x_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1)) +
facet_wrap(~ type, ncol = 1) +
labs(
title = "Change in Abortion Opinion by Religious Tradition (2016 to 2024)",
subtitle = "Each dumbbell shows support in <span style='color:#7570b3;'>2016</span> and <span style='color:#d95f02;'>2024</span> for each group",
x = NULL, y = NULL,
caption = "@ryanburge\nData: Cooperative Election Study, 2016 + 2024"
) +
theme_rb(legend = TRUE) +
theme(strip.text = element_text(size = 25),
plot.subtitle = ggtext::element_markdown())
# Save
save("dumbbell_abortion_2016_2024.png", ht = 10)
aaa1 <- cces24 %>%
mutate(ab = CC24_444c) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
mean_ci(ab, wt = commonweight, ci = .84) %>%
mutate(trad2 = "Entire Sample")
aaa2 <- cces24 %>%
cces_trad(religpew) %>%
mutate(ab = CC24_444c) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
group_by(trad2) %>%
mean_ci(ab, wt = commonweight, ci = .84)
one <- bind_rows(aaa1, aaa2) %>%
mutate(type = "Prohibit Abortion Pills Through the Mail")
aaa1 <- cces24 %>%
mutate(ab = CC24_444d) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
mean_ci(ab, wt = commonweight, ci = .84) %>%
mutate(trad2 = "Entire Sample")
aaa2 <- cces24 %>%
cces_trad(religpew) %>%
mutate(ab = CC24_444d) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
group_by(trad2) %>%
mean_ci(ab, wt = commonweight, ci = .84)
two <- bind_rows(aaa1, aaa2) %>%
mutate(type = "Prohibit Women Traveling Out of State to Receive an Abortion")
aaa1 <- cces24 %>%
mutate(ab = CC24_445b) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
mean_ci(ab, wt = commonweight, ci = .84) %>%
mutate(trad2 = "Entire Sample")
aaa2 <- cces24 %>%
cces_trad(religpew) %>%
mutate(ab = CC24_445b) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
group_by(trad2) %>%
mean_ci(ab, wt = commonweight, ci = .84)
three <- bind_rows(aaa1, aaa2) %>%
mutate(type = "Constitution Doesn't Protect Right to an Abortion")
all <- bind_rows(one, two, three) %>% filter(trad2 != "Unclassified")
# Pull out the Entire Sample means for each type
issue_means <- all %>%
filter(trad2 == "Entire Sample") %>%
select(type, mean) %>%
rename(avg = mean)
all_ordered <- all %>%
filter(trad2 != "Entire Sample") %>%
group_by(type) %>%
mutate(trad2_reorder = fct_reorder(trad2, mean)) %>%
ungroup()
religion_colors <- c(
"#1b9e77", # White Evangelical
"#d95f02", # Non-White Evangelical
"#7570b3", # Mainline
"#e7298a", # Black Protestant
"#66a61e", # White Catholic
"#e6ab02", # Non-White Catholic
"#a6761d", # Mormon
"#666666", # Orthodox
"#1f78b4", # Jewish
"#b2df8a", # Muslim
"#33a02c", # Buddhist
"#fb9a99", # Hindu
"#e31a1c", # Atheist
"#ff7f00", # Agnostic
"#6a3d9a", # Nothing in Particular
"#b15928" # Unclassified
)
# Plot
all_ordered %>%
filter(trad2 != "Entire Sample") %>% # omit the overall bar if not wanted
ggplot(aes(x = trad2_reorder, y = mean, fill = trad2)) +
geom_col(color = "black") +
facet_wrap(~ type, scales = "free_y", ncol = 1) +
geom_hline(data = issue_means, aes(yintercept = avg),
linetype = "dashed", color = "black", linewidth = 0.7) +
coord_flip() +
theme_rb() +
scale_fill_manual(values = religion_colors) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
labs(
x = NULL, y = "Share Agreeing",
title = "Religious Group Support for Anti-Abortion Policies",
caption = "@ryanburge\nData: Cooperative Election Study 2024"
) +
lab_bar(above = TRUE, pos = .025, sz = 5, type = mean) +
theme(strip.text = element_text(size = 13), legend.position = "none")
save('ces24_abortion_facets.png', ht = 10)
gg1 <- cces24 %>%
cces_trad(religpew) %>%
mutate(age = 2024 - birthyr) %>%
mutate(age2 = frcode(age <= 35 ~ "18-35",
age >= 36 & age <= 49 ~ "36-49",
age >= 50 & age <= 64 ~ "50-64",
age >= 65 ~ "65+")) %>%
mutate(ab = CC24_324d) %>%
mutate(ab = case_when(ab == 1 ~ 1,
ab == 2 ~ 0)) %>%
group_by(trad2, age2) %>%
mean_ci(ab, wt = commonweight, ci = .84)
age4_colors <- c(
"18-35" = "#1b9e77", # teal
"36-49" = "#d95f02", # orange
"50-64" = "#7570b3", # purple
"65+" = "#e7298a" # pink
)
gg1 %>%
ggplot(., aes(x = age2, y = mean, fill = age2)) +
geom_col(color = "black") +
facet_wrap(~ trad2) +
error_bar() +
theme_rb() +
y_pct() +
scale_fill_manual(values = age4_colors) +
lab_bar_white(above = FALSE, type = mean, sz = 5, pos = .075) +
theme(strip.text = element_text(size = 14)) +
labs(x = "", y = "", title = "Expand access to abortion, including making it more affordable, broadening the\ntypes of providers who can offer care, and protecting access to abortion clinics",
caption = "@ryanburge\nData: Cooperative Election Study, 2024")
save("expand_access24_trad2_age2.png", ht = 12, wd = 8)
# Define the common pattern as a function to DRY
ab_summary <- function(df, var, label) {
df %>%
cces_pid3(pid7) %>%
mutate(ab = case_when({{ var }} == 1 ~ 1,
{{ var }} == 2 ~ 0)) %>%
group_by(year, pid3) %>%
mean_ci(ab, wt = weight, ci = 0.84) %>%
mutate(type = label)
}
# Generate each summary
ab_all <- ab_summary(cces, ab_choice, "Allow for Any Reason")
ab_never <- ab_summary(cces, ab_never, "Illegal in All Circumstances")
both <- bind_rows(ab_all, ab_never) %>% filter(pid3 != "NA")
label_data <- both %>%
filter(!is.na(mean)) %>% # only keep actual data rows
group_by(type, pid3) %>%
slice_min(order_by = year, n = 1, with_ties = FALSE) %>%
bind_rows(
both %>%
filter(!is.na(mean)) %>%
group_by(type, pid3) %>%
slice_max(order_by = year, n = 1, with_ties = FALSE)
) %>%
mutate(
label = percent(mean, accuracy = 1),
hjust = ifelse(year == min(year), 1.1, -0.1)
)
type_colors <- c(
"Allow for Any Reason" = "#1b9e77", # Deep teal
"Illegal in All Circumstances" = "#d95f02" # Burnt orange
)
both %>%
ggplot(aes(x = year, y = mean, color = type, group = type)) +
geom_line() +
geom_point(stroke = 1, shape = 21, fill = 'white') +
geom_text(data = label_data,
aes(label = label, hjust = hjust),
vjust = -0.3, size = 4.2, show.legend = FALSE,
family = "font") +
facet_wrap(~ pid3) +
y_pct() +
scale_color_manual(values = type_colors) +
scale_x_continuous(limits = c(2013, 2025), breaks = c(2014, 2016, 2018, 2020, 2022, 2024)) +
theme_rb(legend = TRUE) +
theme(legend.text = element_text(size = 20)) +
labs(
x = "", y = "",
title = "Abortion Opinion by Political Partisanship Over the Last Decade",
caption = "@ryanburge\nData: Cooperative Election Study, 2014–2024"
)
save("ab_pid3_2scenarios.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment