-
-
Save ryanburge/f98d623642477983397f7a7cf75ae9de to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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