-
-
Save ryanburge/2bf701a180c866b547aef226a91a6cde 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
| # helper to avoid repeating yourself | |
| make_reltrad_by_year <- function(dat, wt_col) { | |
| dat %>% | |
| gss_reltrad6(reltrad) %>% | |
| group_by(year) %>% | |
| ct(reltrad, wt = {{ wt_col }}) | |
| } | |
| # 1972–2002 → WTSSPS | |
| gg_pre2004 <- gss %>% | |
| filter(year <= 2002) %>% | |
| make_reltrad_by_year(wtssps) | |
| # 2004–2024 → WTSSNRPS (preferred where available) | |
| gg_2004_2024 <- gss %>% | |
| filter(year >= 2004, year <= 2024) %>% | |
| make_reltrad_by_year(wtssnrps) | |
| # bind + tidy | |
| gg_all <- bind_rows(gg_pre2004, gg_2004_2024) %>% | |
| arrange(year, reltrad) | |
| graph <- gg_all %>% filter(reltrad != "NA") | |
| graph %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 2002, y = .29, word = "Catholic", sz = 8) + | |
| add_text(x = 2002, y = .22, word = "Evangelical", sz = 8) + | |
| add_text(x = 1985, y = .175, word = "Mainline", sz = 8) + | |
| add_text(x = 2021, y = .30, word = "Nones", sz = 8) + | |
| add_text(x = 2002, y = .04, word = "Black Prot.", sz = 8) + | |
| add_text(x = 2023, y = .13, word = "Other", sz = 8) + | |
| labs(x = "Year", y = "", title = "The American Religious Landscape, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_reltrad6_2024.png") | |
| graph %>% | |
| filter(reltrad == "Evangelical") %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 1972, y = .167, word = "18%", sz = 8) + | |
| add_text(x = 1991, y = .305, word = "29%", sz = 8) + | |
| add_text(x = 2012, y = .260, word = "25%", sz = 8) + | |
| add_text(x = 2021, y = .150, word = "17%", sz = 8) + | |
| add_text(x = 2024, y = .210, word = "19.5%", sz = 8) + | |
| theme(plot.title = element_text(size = 22)) + | |
| labs(x = "Year", y = "", title = "American Evangelicals, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_evangelicals_2024.png") | |
| graph %>% | |
| filter(reltrad == "Mainline") %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 1975, y = .315, word = "30%", sz = 8) + | |
| add_text(x = 1986, y = .178, word = "19%", sz = 8) + | |
| add_text(x = 2004, y = .110, word = "12%", sz = 8) + | |
| add_text(x = 2016, y = .085, word = "10%", sz = 8) + | |
| add_text(x = 2024, y = .070, word = "8.7%", sz = 8) + | |
| theme(plot.title = element_text(size = 22)) + | |
| labs(x = "Year", y = "", title = "American Mainline Protestants, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_mainline_2024.png") | |
| graph %>% | |
| filter(reltrad == "Catholic") %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 1976, y = .2875, word = "27%", sz = 8) + | |
| add_text(x = 1994, y = .298, word = "28%", sz = 8) + | |
| add_text(x = 2010, y = .285, word = "27%", sz = 8) + | |
| add_text(x = 2024, y = .200, word = "22%", sz = 8) + | |
| theme(plot.title = element_text(size = 22)) + | |
| labs(x = "Year", y = "", title = "American Catholics, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_catholics_2024.png") | |
| graph %>% | |
| filter(reltrad == "Black Prot.") %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 1972, y = .105, word = "9%", sz = 8) + | |
| add_text(x = 1988, y = .0525, word = "7%", sz = 8) + | |
| add_text(x = 2016, y = .0355, word = "5%", sz = 8) + | |
| add_text(x = 2024, y = .0305, word = "4.4%", sz = 8) + | |
| theme(plot.title = element_text(size = 22)) + | |
| labs(x = "Year", y = "", title = "American Black Protestants, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_black_prot_2024.png") | |
| graph %>% | |
| filter(reltrad == "No Religion") %>% | |
| ggplot(., aes(x = year, y = pct, color = reltrad, group = reltrad)) + | |
| geom_line() + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual( | |
| values = c( | |
| "Evangelical" = "#FF4E00", # vivid orange | |
| "Mainline" = "#0077FF", # bright blue | |
| "Catholic" = "#22CC22", # bright green | |
| "Black Prot." = "#A500FF", # electric purple | |
| "No Religion" = "#FF006E", # hot pink/red | |
| "Other Faith" = "#FFD700" # gold | |
| ) | |
| ) + | |
| scale_y_continuous(labels = percent, limits = c(0, .32)) + | |
| add_text(x = 1972, y = .040, word = "5.5%", sz = 8) + | |
| add_text(x = 1991, y = .05, word = "6.7%", sz = 8) + | |
| add_text(x = 2006, y = .180, word = "16%", sz = 8) + | |
| add_text(x = 2021, y = .30, word = "28%", sz = 8) + | |
| add_text(x = 2024, y = .2375, word = "25.2%", sz = 8) + | |
| theme(plot.title = element_text(size = 22)) + | |
| labs(x = "Year", y = "", title = "Americans With No Religious Affiliation, 1972-2024", caption = "@ryanburge | Data: General Social Survey, 1972-2024") | |
| save("gss_nones_2024.png") | |
| # --- 1) Define generations from birth cohort --- | |
| # GSS has COHORT = birth year. If missing, fall back to year - age. | |
| gss_gen <- gss %>% | |
| mutate( | |
| cohort_by = ifelse(!is.na(cohort), cohort, year - age), | |
| gen = frcode( | |
| cohort_by >= 1928 & cohort_by <= 1945 ~ "Silent", | |
| cohort_by >= 1946 & cohort_by <= 1964 ~ "Boomer", | |
| cohort_by >= 1965 & cohort_by <= 1980 ~ "Gen X", | |
| cohort_by >= 1981 & cohort_by <= 1996 ~ "Millennial", | |
| cohort_by >= 1997 & cohort_by <= 2012 ~ "Gen Z", | |
| TRUE ~ NA_character_ | |
| ) | |
| ) | |
| # --- 2) Helper to reduce repetition (same as before) --- | |
| make_by_year <- function(dat, var, wt_col) { | |
| dat %>% | |
| group_by(year) %>% | |
| ct({{ var }}, wt = {{ wt_col }}) | |
| } | |
| # --- 3) Weights by era (same rule as reltrad) --- | |
| gg_gen_pre2004 <- gss_gen %>% | |
| filter(year <= 2002) %>% | |
| make_by_year(gen, wtssps) | |
| gg_gen_2004_2024 <- gss_gen %>% | |
| filter(year >= 2004, year <= 2024) %>% | |
| make_by_year(gen, wtssnrps) | |
| # --- 4) Bind and clean --- | |
| gen_graph <- bind_rows(gg_gen_pre2004, gg_gen_2004_2024) %>% | |
| filter(gen != "NA") %>% | |
| arrange(year, gen) | |
| # --- 5) Bright, high-contrast palette --- | |
| gen_pal <- c( | |
| "Silent" = "#A500FF", # electric purple | |
| "Boomer" = "#0077FF", # bright blue | |
| "Gen X" = "#22CC22", # bright green | |
| "Millennial" = "#FF4E00", # vivid orange | |
| "Gen Z" = "#FF006E" # hot pink/red | |
| ) | |
| # --- 6) Main generations time series plot --- | |
| gen_graph %>% | |
| ggplot(aes(x = year, y = pct, color = gen, group = gen)) + | |
| geom_line(linewidth = 1.2) + | |
| geom_point(stroke = 1, shape = 21, fill = "white") + | |
| theme_rb(legend = TRUE) + | |
| scale_color_manual(values = gen_pal) + | |
| scale_y_continuous(labels = scales::percent, limits = c(0, .40)) + | |
| labs( | |
| x = "Year", y = "", | |
| title = "Generational Composition of U.S. Adults, 1972–2024", | |
| caption = "@ryanburge | Data: General Social Survey, 1972–2024" | |
| ) | |
| save("gss_generations_1972_2024.png") | |
| # --- 0) Palettes + helpers --- | |
| gen_pal <- c( | |
| "Silent" = "#A500FF", | |
| "Boomer" = "#0077FF", | |
| "Gen X" = "#22CC22", | |
| "Millennial" = "#FF4E00", | |
| "Gen Z" = "#FF006E" | |
| ) | |
| # --- 1) Build generations + reltrad; make nonreligious flag --- | |
| gss_gen_rel <- gss %>% | |
| # COHORT is birth year in GSS; if missing, derive as year - age | |
| mutate( | |
| cohort_by = ifelse(!is.na(cohort), cohort, year - age), | |
| gen = frcode( | |
| cohort_by >= 1928 & cohort_by <= 1945 ~ "Silent", | |
| cohort_by >= 1946 & cohort_by <= 1964 ~ "Boomer", | |
| cohort_by >= 1965 & cohort_by <= 1980 ~ "Gen X", | |
| cohort_by >= 1981 & cohort_by <= 1996 ~ "Millennial", | |
| cohort_by >= 1997 & cohort_by <= 2012 ~ "Gen Z" | |
| ) | |
| ) %>% | |
| gss_reltrad6(reltrad) %>% | |
| mutate(nones = frcode(reltrad == "No Religion" ~ "Non-religious", | |
| reltrad != "No Religion" ~ "Religious")) | |
| # --- 2) Helper to compute % nones by year x gen with a given weight --- | |
| pct_nones <- function(dat, wt_col) { | |
| dat %>% | |
| filter(!is.na(gen)) %>% | |
| group_by(year, gen) %>% | |
| ct(nones, wt = {{ wt_col }}) %>% | |
| filter(nones == "Non-religious") %>% | |
| select(year, gen, pct) | |
| } | |
| # --- 3) Apply weights by era and bind --- | |
| gen_nones_pre2004 <- gss_gen_rel %>% | |
| filter(year <= 2002) %>% | |
| pct_nones(wtssps) | |
| gen_nones_2004_2024 <- gss_gen_rel %>% | |
| filter(year >= 2004, year <= 2024) %>% | |
| pct_nones(wtssnrps) | |
| gen_nones <- bind_rows(gen_nones_pre2004, gen_nones_2004_2024) %>% | |
| arrange(year, gen) | |
| # --- 4) Plot: one time series with a line per generation --- | |
| gen_nones %>% | |
| ggplot(aes(x = year, y = pct, color = gen, group = gen)) + | |
| geom_line(linewidth = 1.2) + | |
| geom_point(shape = 21, stroke = 1, fill = "white") + | |
| theme_rb() + | |
| scale_color_manual(values = gen_pal) + | |
| scale_y_continuous(labels = scales::percent, limits = c(0, 0.60)) + | |
| labs( | |
| x = "Year", y = "", | |
| title = "Share Non-Religious by Generation, 1972–2024", | |
| caption = "@ryanburge | Data: General Social Survey, 1972–2024" | |
| ) | |
| save("gss_nones_by_generation_1972_2024.png") | |
| # 1) Build generations + nones flag | |
| gss_gen_rel <- gss %>% | |
| mutate( | |
| cohort_by = ifelse(!is.na(cohort), cohort, year - age), | |
| gen = frcode( | |
| cohort_by >= 1928 & cohort_by <= 1945 ~ "Silent", | |
| cohort_by >= 1946 & cohort_by <= 1964 ~ "Boomer", | |
| cohort_by >= 1965 & cohort_by <= 1980 ~ "Gen X", | |
| cohort_by >= 1981 & cohort_by <= 1996 ~ "Millennial", | |
| cohort_by >= 1997 & cohort_by <= 2012 ~ "Gen Z" | |
| ) | |
| ) %>% | |
| gss_reltrad6(reltrad) %>% | |
| mutate(nones = as.numeric(reltrad == "No Religion")) | |
| # 2) Compute weighted mean + 84% CI by year x generation (2016+) | |
| gen_nones_ci <- gss_gen_rel %>% | |
| filter(year >= 2016, !is.na(gen)) %>% | |
| group_by(year, gen) %>% | |
| mean_ci(nones, wt = wtssnrps, ci = .84) %>% # returns mean, sd, n, se, lower, upper (per your function) | |
| ungroup() | |
| gen_nones_ci %>% | |
| ggplot(aes(x = factor(year), y = mean, fill = factor(year))) + | |
| geom_col(color = "black") + | |
| geom_errorbar(aes(ymin = lower, ymax = upper), width = .2, linewidth = .6) + | |
| theme_rb() + | |
| # --- white text for darker (early) bars, black for lighter ones --- | |
| geom_text( | |
| aes( | |
| y = 0.04, | |
| label = paste0(round(mean * 100, 0), "%"), | |
| color = factor(year) | |
| ), | |
| size = 6, family = "font" | |
| ) + | |
| scale_color_manual( | |
| values = c( | |
| # adjust the number of colors to your years | |
| "2016" = "white", | |
| "2018" = "white", | |
| "2021" = "white", | |
| "2022" = "black", | |
| "2024" = "black" | |
| ), | |
| guide = "none" | |
| ) + | |
| scale_fill_viridis_d(option = "magma", begin = 0.1, end = 0.9) + | |
| scale_y_continuous(labels = scales::percent, limits = c(0, 0.70)) + | |
| facet_wrap(~ gen) + | |
| labs( | |
| x = "Year", y = "", | |
| title = "Share Non-Religious by Generation, 2016–2024", | |
| fill = "Year", | |
| caption = "@ryanburge | Data: General Social Survey, 2016–2024" | |
| ) | |
| save("gss_nones_by_generation_2016_2024_with84CI.png", ht = 8) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment