Skip to content

Instantly share code, notes, and snippets.

@ryanburge
Created January 27, 2026 02:44
Show Gist options
  • Select an option

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

Select an option

Save ryanburge/018c26c6627fa0a44188cec8444acaaa to your computer and use it in GitHub Desktop.
# Function to process each year's data
process_year <- function(df, year) {
# Adjust variable names based on year
prefix <- paste0("CC", substr(year, 3, 4), "_300b_")
df %>%
mutate(
abc = case_when(get(paste0(prefix, "1")) == 1 ~ 1, get(paste0(prefix, "1")) == 2 ~ 0),
cbs = case_when(get(paste0(prefix, "2")) == 1 ~ 1, get(paste0(prefix, "2")) == 2 ~ 0),
nbc = case_when(get(paste0(prefix, "3")) == 1 ~ 1, get(paste0(prefix, "3")) == 2 ~ 0),
cnn = case_when(get(paste0(prefix, "4")) == 1 ~ 1, get(paste0(prefix, "4")) == 2 ~ 0),
fox = case_when(get(paste0(prefix, "5")) == 1 ~ 1, get(paste0(prefix, "5")) == 2 ~ 0),
msnbc = case_when(get(paste0(prefix, "6")) == 1 ~ 1, get(paste0(prefix, "6")) == 2 ~ 0),
pbs = case_when(get(paste0(prefix, "7")) == 1 ~ 1, get(paste0(prefix, "7")) == 2 ~ 0),
other = case_when(get(paste0(prefix, "8")) == 1 ~ 1, get(paste0(prefix, "8")) == 2 ~ 0)
) %>%
select(abc, cbs, nbc, cnn, fox, msnbc, pbs, other, commonweight) %>%
na.omit() %>%
mutate(year = year)
}
# Process all three years and combine
combined <- bind_rows(
process_year(cces20, "2020"),
process_year(cces22, "2022"),
process_year(cces24, "2024")
)
# Calculate mean_ci for each network by year with weights
graph <- combined %>%
pivot_longer(cols = abc:other, names_to = "network", values_to = "value") %>%
group_by(year, network) %>%
mean_ci(value, wt = commonweight, ci = .84) %>%
mutate(
network = frcode(
network == "abc" ~ "ABC",
network == "cbs" ~ "CBS",
network == "nbc" ~ "NBC",
network == "cnn" ~ "CNN",
network == "fox" ~ "Fox News",
network == "msnbc" ~ "MSNBC",
network == "pbs" ~ "PBS",
network == "other" ~ "Other"
),
mean = round(mean, 2)
)
graph %>%
ggplot(aes(x = fct_rev(network), y = mean, color = factor(year))) +
geom_point(size = 3, position = position_dodge(width = 0.5)) +
coord_flip() +
scale_color_manual(values = c("2020" = "#2E86AB",
"2022" = "#A23B72",
"2024" = "#F18F01"),
name = "Year") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
labs(x = NULL,
y = "",
title = "In the past 24 Hours, which of these networks did you watch?",
caption = "@ryanburge | Data: Cooperative Election Study, 2020-2024") +
theme_rb(legend = TRUE) +
theme(legend.text = element_text(size = 20))
save("avg_look_network.png", ht = 5)
# Process 2024 data with generation variable
gen24 <- cces24 %>%
mutate(
abc = case_when(CC24_300b_1 == 1 ~ 1, CC24_300b_1 == 2 ~ 0),
cbs = case_when(CC24_300b_2 == 1 ~ 1, CC24_300b_2 == 2 ~ 0),
nbc = case_when(CC24_300b_3 == 1 ~ 1, CC24_300b_3 == 2 ~ 0),
cnn = case_when(CC24_300b_4 == 1 ~ 1, CC24_300b_4 == 2 ~ 0),
fox = case_when(CC24_300b_5 == 1 ~ 1, CC24_300b_5 == 2 ~ 0),
msnbc = case_when(CC24_300b_6 == 1 ~ 1, CC24_300b_6 == 2 ~ 0),
pbs = case_when(CC24_300b_7 == 1 ~ 1, CC24_300b_7 == 2 ~ 0),
other = case_when(CC24_300b_8 == 1 ~ 1, CC24_300b_8 == 2 ~ 0)
) %>%
mutate(generation = frcode(
birthyr >= 1997 ~ "Gen Z",
birthyr >= 1981 & birthyr <= 1996 ~ "Millennial",
birthyr >= 1965 & birthyr <= 1980 ~ "Gen X",
birthyr >= 1946 & birthyr <= 1964 ~ "Boomer",
birthyr <= 1945 ~ "Silent"
)) %>%
select(abc, cbs, nbc, cnn, fox, msnbc, pbs, other, generation, commonweight) %>%
na.omit()
# Calculate by generation
gg <- gen24 %>%
pivot_longer(cols = abc:other, names_to = "network", values_to = "value") %>%
group_by(generation, network) %>%
mean_ci(value, wt = commonweight, ci = .84) %>%
mutate(
network = frcode(
network == "abc" ~ "ABC",
network == "cbs" ~ "CBS",
network == "nbc" ~ "NBC",
network == "cnn" ~ "CNN",
network == "fox" ~ "Fox News",
network == "msnbc" ~ "MSNBC",
network == "pbs" ~ "PBS",
network == "other" ~ "Other",
network == "none" ~ "None"
)
)
gg %>%
filter(network != "None") %>%
ggplot(aes(x = generation, y = mean, color = network, group = network)) +
geom_line(linewidth = 1.2) +
geom_point(stroke = 1, shape = 21, fill = 'white', size = 3) +
scale_x_discrete(limits = c("Silent", "Boomer", "Gen X", "Millennial", "Gen Z")) +
scale_color_manual(values = c(
"ABC" = "#E63946",
"CBS" = "#F77F00",
"NBC" = "#FCBF49",
"CNN" = "#06A77D",
"Fox News" = "#118AB2",
"MSNBC" = "#073B4C",
"PBS" = "#8338EC",
"Other" = "#999999"
), name = NULL) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
labs(x = NULL,
y = "Share Who Watch",
title = "Cable News Viewership by Generation",
caption = "@ryanburge | Data: Cooperative Election Study 2024") +
theme_rb(legend = TRUE) +
theme(legend.text = element_text(size = 20))
save("gen_watch_networks.png")
small <- cces24 %>%
mutate(abc = case_when(CC24_300b_1 == 1 ~ 1, CC24_300b_1 == 2 ~ 0)) %>%
mutate(cbs = case_when(CC24_300b_2 == 1 ~ 1, CC24_300b_2 == 2 ~ 0)) %>%
mutate(nbc = case_when(CC24_300b_3 == 1 ~ 1, CC24_300b_3 == 2 ~ 0)) %>%
mutate(cnn = case_when(CC24_300b_4 == 1 ~ 1, CC24_300b_4 == 2 ~ 0)) %>%
mutate(fox = case_when(CC24_300b_5 == 1 ~ 1, CC24_300b_5 == 2 ~ 0)) %>%
mutate(msnbc = case_when(CC24_300b_6 == 1 ~ 1, CC24_300b_6 == 2 ~ 0)) %>%
mutate(pbs = case_when(CC24_300b_7 == 1 ~ 1, CC24_300b_7 == 2 ~ 0)) %>%
mutate(other = case_when(CC24_300b_8 == 1 ~ 1, CC24_300b_8 == 2 ~ 0)) %>%
cces_trad(religpew) %>%
select(abc, cbs, nbc, cnn, fox, msnbc, pbs, other, trad2) %>%
as_tibble() %>%
na.omit()
graph <- small %>%
group_by(trad2) %>%
summarise(across(abc:other, ~ mean(.x, na.rm=TRUE))) %>%
pivot_longer(!trad2) %>%
mutate(name = frcode(name == "abc" ~ "ABC",
name == "cbs" ~ "CBS",
name == "nbc" ~ "NBC",
name == "cnn" ~ "CNN",
name == "fox" ~ "Fox\nNews",
name == "msnbc" ~ "MSNBC",
name == "pbs" ~ "PBS",
name == "other" ~ "Other")) %>%
rename(mean = value) %>%
mutate(mean = round(mean, 2))
graph %>%
ggplot(., aes(x= name, y = fct_rev(trad2))) +
geom_tile(aes(fill = mean), color = "black") +
scale_fill_gradient2(low = "#3A506B", mid = "#F4E285", high = "#BC4B51", midpoint = .33) +
theme_rb() +
geom_text(aes(x= name, y = trad2, label = paste0(mean*100, '%')), size = 5, family = "bold") +
labs(x= "News Network", y = "",
title = "Watched This Network in the Past 24 Hours",
caption = "@ryanburge | Data: Cooperative Election Study, 2024")
save("news_network_heat24.png", wd = 6)
######
# Process 2020 data
small20 <- cces20 %>%
mutate(abc = case_when(CC20_300b_1 == 1 ~ 1, CC20_300b_1 == 2 ~ 0)) %>%
mutate(cbs = case_when(CC20_300b_2 == 1 ~ 1, CC20_300b_2 == 2 ~ 0)) %>%
mutate(nbc = case_when(CC20_300b_3 == 1 ~ 1, CC20_300b_3 == 2 ~ 0)) %>%
mutate(cnn = case_when(CC20_300b_4 == 1 ~ 1, CC20_300b_4 == 2 ~ 0)) %>%
mutate(fox = case_when(CC20_300b_5 == 1 ~ 1, CC20_300b_5 == 2 ~ 0)) %>%
mutate(msnbc = case_when(CC20_300b_6 == 1 ~ 1, CC20_300b_6 == 2 ~ 0)) %>%
mutate(pbs = case_when(CC20_300b_7 == 1 ~ 1, CC20_300b_7 == 2 ~ 0)) %>%
mutate(other = case_when(CC20_300b_8 == 1 ~ 1, CC20_300b_8 == 2 ~ 0)) %>%
cces_trad(religpew) %>%
select(abc, cbs, nbc, cnn, fox, msnbc, pbs, other, trad2) %>%
as_tibble() %>%
na.omit()
graph20 <- small20 %>%
group_by(trad2) %>%
summarise(across(abc:other, ~ mean(.x, na.rm=TRUE))) %>%
pivot_longer(!trad2) %>%
mutate(name = frcode(name == "abc" ~ "ABC",
name == "cbs" ~ "CBS",
name == "nbc" ~ "NBC",
name == "cnn" ~ "CNN",
name == "fox" ~ "Fox\nNews",
name == "msnbc" ~ "MSNBC",
name == "pbs" ~ "PBS",
name == "other" ~ "Other")) %>%
rename(mean20 = value)
# Process 2024 data
small24 <- cces24 %>%
mutate(abc = case_when(CC24_300b_1 == 1 ~ 1, CC24_300b_1 == 2 ~ 0)) %>%
mutate(cbs = case_when(CC24_300b_2 == 1 ~ 1, CC24_300b_2 == 2 ~ 0)) %>%
mutate(nbc = case_when(CC24_300b_3 == 1 ~ 1, CC24_300b_3 == 2 ~ 0)) %>%
mutate(cnn = case_when(CC24_300b_4 == 1 ~ 1, CC24_300b_4 == 2 ~ 0)) %>%
mutate(fox = case_when(CC24_300b_5 == 1 ~ 1, CC24_300b_5 == 2 ~ 0)) %>%
mutate(msnbc = case_when(CC24_300b_6 == 1 ~ 1, CC24_300b_6 == 2 ~ 0)) %>%
mutate(pbs = case_when(CC24_300b_7 == 1 ~ 1, CC24_300b_7 == 2 ~ 0)) %>%
mutate(other = case_when(CC24_300b_8 == 1 ~ 1, CC24_300b_8 == 2 ~ 0)) %>%
cces_trad(religpew) %>%
select(abc, cbs, nbc, cnn, fox, msnbc, pbs, other, trad2) %>%
as_tibble() %>%
na.omit()
graph24 <- small24 %>%
group_by(trad2) %>%
summarise(across(abc:other, ~ mean(.x, na.rm=TRUE))) %>%
pivot_longer(!trad2) %>%
mutate(name = frcode(name == "abc" ~ "ABC",
name == "cbs" ~ "CBS",
name == "nbc" ~ "NBC",
name == "cnn" ~ "CNN",
name == "fox" ~ "Fox\nNews",
name == "msnbc" ~ "MSNBC",
name == "pbs" ~ "PBS",
name == "other" ~ "Other")) %>%
rename(mean24 = value)
# Calculate change
change <- graph20 %>%
left_join(graph24, by = c("trad2", "name")) %>%
mutate(diff = mean24 - mean20) %>%
mutate(diff = round(diff, 3))
# Visualize the change
change %>%
ggplot(aes(x = name, y = fct_rev(trad2))) +
geom_tile(aes(fill = diff), color = "black") +
scale_fill_gradient2(low = "#2E86AB", mid = "white", high = "#BC4B51", midpoint = 0) +
theme_rb() +
geom_text(aes(label = ifelse(diff > 0, paste0("+", diff*100), paste0(diff*100))),
size = 4, family = "font") +
labs(x = "News Network", y = "Religious Tradition",
title = "Change in Network Viewership: 2020 to 2024",
subtitle = "Percentage Point Change",
caption = "@ryanburge | Data: CCES 2020, 2024")
save("news_network_change_2024.png", wd = 6)
# Fox News vs MSNBC gap by religious tradition
comp <- small24 %>%
select(trad2, fox, msnbc) %>%
group_by(trad2) %>%
summarise(
fox = mean(fox, na.rm = TRUE),
msnbc = mean(msnbc, na.rm = TRUE)
) %>%
mutate(gap = fox - msnbc) %>%
arrange(desc(gap))
comp %>%
ggplot(aes(x = fct_reorder(trad2, gap), y = gap)) +
geom_col(aes(fill = gap > 0), color = "black") +
coord_flip() +
scale_fill_manual(values = c("TRUE" = "#BC4B51", "FALSE" = "#2E86AB")) +
geom_hline(yintercept = 0, linewidth = 1) +
geom_text(aes(label = paste0(round(gap*100, 0), "%"),
hjust = ifelse(gap > 0, -0.1, 1.1)),
size = 4, family = "bold") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), limits = c(-.33, .5)) +
theme_rb() +
theme(legend.position = "none") +
labs(x = NULL,
y = "Fox News Advantage (Negative = MSNBC Advantage)",
title = "Fox News vs MSNBC Viewership Gap by Religion",
subtitle = "Difference in Share Who Watched Each Network",
caption = "@ryanburge | Data: Cooperative Election Study, 2024")
save("fox_msnbc_gap_religion24.png")
######
# Process 2020 data with generation
gen20 <- cces20 %>%
mutate(abc = case_when(CC20_300b_1 == 1 ~ 1, CC20_300b_1 == 2 ~ 0)) %>%
mutate(cbs = case_when(CC20_300b_2 == 1 ~ 1, CC20_300b_2 == 2 ~ 0)) %>%
mutate(nbc = case_when(CC20_300b_3 == 1 ~ 1, CC20_300b_3 == 2 ~ 0)) %>%
mutate(cnn = case_when(CC20_300b_4 == 1 ~ 1, CC20_300b_4 == 2 ~ 0)) %>%
mutate(fox = case_when(CC20_300b_5 == 1 ~ 1, CC20_300b_5 == 2 ~ 0)) %>%
mutate(msnbc = case_when(CC20_300b_6 == 1 ~ 1, CC20_300b_6 == 2 ~ 0)) %>%
mutate(pbs = case_when(CC20_300b_7 == 1 ~ 1, CC20_300b_7 == 2 ~ 0)) %>%
mutate(other = case_when(CC20_300b_8 == 1 ~ 1, CC20_300b_8 == 2 ~ 0)) %>%
cces_trad(religpew) %>%
mutate(generation = frcode(
birthyr >= 1997 ~ "Gen Z",
birthyr >= 1981 & birthyr <= 1996 ~ "Millennial",
birthyr >= 1965 & birthyr <= 1980 ~ "Gen X",
birthyr >= 1946 & birthyr <= 1964 ~ "Boomer",
birthyr <= 1945 ~ "Silent"
)) %>%
select(fox, msnbc, cnn, trad2, generation) %>%
na.omit()
# Process 2024 data with generation
gen24 <- cces24 %>%
mutate(abc = case_when(CC24_300b_1 == 1 ~ 1, CC24_300b_1 == 2 ~ 0)) %>%
mutate(cbs = case_when(CC24_300b_2 == 1 ~ 1, CC24_300b_2 == 2 ~ 0)) %>%
mutate(nbc = case_when(CC24_300b_3 == 1 ~ 1, CC24_300b_3 == 2 ~ 0)) %>%
mutate(cnn = case_when(CC24_300b_4 == 1 ~ 1, CC24_300b_4 == 2 ~ 0)) %>%
mutate(fox = case_when(CC24_300b_5 == 1 ~ 1, CC24_300b_5 == 2 ~ 0)) %>%
mutate(msnbc = case_when(CC24_300b_6 == 1 ~ 1, CC24_300b_6 == 2 ~ 0)) %>%
mutate(pbs = case_when(CC24_300b_7 == 1 ~ 1, CC24_300b_7 == 2 ~ 0)) %>%
mutate(other = case_when(CC24_300b_8 == 1 ~ 1, CC24_300b_8 == 2 ~ 0)) %>%
cces_trad(religpew) %>%
mutate(generation = frcode(
birthyr >= 1997 ~ "Gen Z",
birthyr >= 1981 & birthyr <= 1996 ~ "Millennial",
birthyr >= 1965 & birthyr <= 1980 ~ "Gen X",
birthyr >= 1946 & birthyr <= 1964 ~ "Boomer",
birthyr <= 1945 ~ "Silent"
)) %>%
select(fox, msnbc, cnn, trad2, generation) %>%
na.omit()
# Calculate Fox-MSNBC gap by generation and religion
gap20 <- gen20 %>%
group_by(generation, trad2) %>%
summarise(gap20 = mean(fox) - mean(msnbc), .groups = "drop")
gap24 <- gen24 %>%
group_by(generation, trad2) %>%
summarise(gap24 = mean(fox) - mean(msnbc), .groups = "drop")
# Combine and calculate change
combined <- gap20 %>%
left_join(gap24, by = c("generation", "trad2")) %>%
mutate(change = gap24 - gap20)
# Visualize - focus on key religious groups
combined %>%
filter(trad2 %in% c("White Evangelical", "Mainline", "White Catholic",
"Atheist", "Agnostic", "Nothing in Particular")) %>%
ggplot(aes(x = generation, y = change, fill = trad2)) +
geom_col(position = "dodge", color = "black") +
scale_x_discrete(limits = c("Gen Z", "Millennial", "Gen X", "Boomer", "Silent")) +
scale_fill_manual(values = c(
"White Evangelical" = "#BC4B51",
"Mainline" = "#F77F00",
"White Catholic" = "#FCBF49",
"Atheist" = "#2E86AB",
"Agnostic" = "#06A77D",
"Nothing in Particular" = "#8338EC"
), name = NULL) +
geom_hline(yintercept = 0, linewidth = 1) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
labs(x = NULL,
y = "Change in Fox-MSNBC Gap",
title = "Change in Fox News Advantage by Generation & Religion",
subtitle = "2020 to 2024 (Positive = More Fox Advantage)",
caption = "@ryanburge | Data: CCES 2020, 2024") +
theme_rb(legend = TRUE)
save("fox_gap_change_gen_religion.png")
# Calculate Fox-MSNBC gap by generation and religion
gap20 <- gen20 %>%
group_by(generation, trad2) %>%
summarise(gap20 = mean(fox) - mean(msnbc), .groups = "drop")
gap24 <- gen24 %>%
group_by(generation, trad2) %>%
summarise(gap24 = mean(fox) - mean(msnbc), .groups = "drop")
# Combine and calculate change
combined <- gap20 %>%
left_join(gap24, by = c("generation", "trad2")) %>%
mutate(change = gap24 - gap20) %>% filter(generation != "Silent")
# Visualize - focus on key religious groups
combined %>%
filter(trad2 %in% c("White Evangelical", "Mainline", "White Catholic",
"Atheist", "Agnostic", "Nothing in Particular")) %>%
ggplot(aes(x = fct_reorder(trad2, change), y = change, color = change > 0)) +
geom_segment(aes(xend = trad2, y = 0, yend = change), linewidth = 1.5) +
geom_point(size = 4) +
geom_text(aes(label = paste0(round(change*100, 0), "%"),
hjust = ifelse(change > 0, -0.5, 1.5)),
size = 3, family = "bold", color = "black") +
coord_flip() +
facet_wrap(~ factor(generation, levels = c("Silent", "Boomer", "Gen X", "Millennial", "Gen Z"))) +
scale_color_manual(values = c("TRUE" = "#BC4B51", "FALSE" = "#2E86AB")) +
geom_hline(yintercept = 0, linewidth = 1) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), limits = c(-.1, .1)) +
labs(x = NULL,
y = "Change in Fox-MSNBC Gap",
title = "Change in Fox News Advantage by Generation & Religion",
subtitle = "2020 to 2024 (Positive = More Fox Advantage)",
caption = "@ryanburge | Data: Cooperative Election Study, 2020 vs 2024") +
theme_rb() +
theme(legend.position = "none")
save("fox_gap_change_gen_religion.png")
# Fox vs MSNBC by generation and religion for 2024
gen24 %>%
filter(trad2 %in% c("White Evangelical", "Mainline", "White Catholic",
"Atheist", "Agnostic", "Nothing in Particular")) %>%
group_by(generation, trad2) %>%
summarise(gap = mean(fox) - mean(msnbc), .groups = "drop") %>%
ggplot(aes(x = fct_reorder(trad2, gap), y = gap, color = gap > 0)) +
geom_segment(aes(xend = trad2, y = 0, yend = gap), linewidth = 1.5) +
geom_point(size = 4) +
geom_text(aes(label = paste0(round(gap*100, 0), "%"),
hjust = ifelse(gap > 0, -0.5, 1.5)),
size = 3, family = "bold", color = "black") +
coord_flip() +
facet_wrap(~ factor(generation, levels = c("Silent", "Boomer", "Gen X", "Millennial", "Gen Z"))) +
scale_color_manual(values = c("TRUE" = "#BC4B51", "FALSE" = "#2E86AB")) +
geom_hline(yintercept = 0, linewidth = 1) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1), limits = c(-.60, .75)) +
labs(x = NULL,
y = "Fox News Advantage (Negative = MSNBC Advantage)",
title = "Fox News vs MSNBC Gap by Generation & Religion",
subtitle = "Difference in Share Who Watched Each Network",
caption = "@ryanburge | Data: Cooperative Election Study, 2024") +
theme_rb() +
theme(legend.position = "none")
save("fox_msnbc_gap_gen_religion24.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment