First-level agenda-setting theory predicts that issues featured prominently in media content often become prominent in the minds of media audiences. Because media outlets have limited time, space, and resources, they must choose which issues receive more or less attention. In doing so, media organizations inevitably prioritize some topics while pushing others lower on the media agenda or off it entirely. Occasionally, two issues may trade prominence over time, with one rising in coverage as the other declines. At other times, both may receive roughly equal attention.
Drawing on what first-level agenda-setting theory suggests about this competition for prominence, this project compares the media agenda prominence of two issues in U.S. immigration coverage: immigrant arrests (enforcement-focused coverage) and immigrant rights (protection-focused coverage). Specifically, the analysis compares the number of stories per week that APNews.com published about each issue between January 1 and September 30, 2025. The results contribute to understanding how media attention toward enforcement versus humanitarian perspectives on immigration fluctuates over time.
Weekly APNews.com coverage volume of immigrant arrests and immigrant rights differed during the first nine months of 2025.
The dependent variable in this analysis was weekly APNews.com coverage volume of the two issues, measured continuously as the number of stories published per week. The independent variable was story topic, measured categorically as either “Immigrant Arrest” or “Immigrant Rights.”
Key words and phrases used to identify stories about immigrant arrests included: “immigrant arrest,” “ICE raid,” “immigration enforcement,” “deportation,” “detention center,” and “DACA.”
Key words and phrases used to identify stories about immigrant rights included: “immigrant right,” “asylum,” “refugee status,” “asylum seeker,” and “temporary protected status.”
The analysis used R to flag and count the number of stories per week containing these terms, then compared the two coverage patterns using line graphs. Eventually, a paired-samples t-test could be used to assess the statistical significance of coverage variation between the two topics.
The figure below summarizes weekly coverage volumes for immigrant arrests and immigrant rights across the analyzed period.
Overall, APNews.com published substantially more stories related to immigrant arrests than to immigrant rights throughout the first nine months of 2025. Coverage of immigrant arrests showed frequent spikes, most notably around Weeks 5, 12, 19, 24, and 26. This is when the number of articles rose sharply. These peaks appear to coincide with periods of heightened national attention to immigration enforcement, such as large-scale ICE operations or political debates over border security.
In contrast, coverage of immigrant rights remained consistently lower, rarely exceeding six stories in a week. Although smaller fluctuations occurred, rights-related coverage never matched the intensity or frequency of enforcement-focused stories. Occasional increases, such as in Weeks 4 and 38, corresponded with discussions of asylum policy changes and humanitarian protections like Temporary Protected Status.
The alternating peaks suggest a potential trade-off effect: when enforcement coverage increased, humanitarian coverage tended to decline. This dynamic demonstrates how two interrelated but ideologically distinct issues, law enforcement versus humanitarian protection, compete for attention on the media agenda. The consistent dominance of immigrant arrest coverage indicates that enforcement remains the primary lens through which immigration is presented to audiences, shaping public understanding of the issue’s relative importance.
# ============================================
# APNews text analysis (First-level agenda-setting theory version)
# ============================================
# ============================================
# --- Load required libraries ---
# ============================================
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("tidytext")) install.packages("tidytext")
library(tidyverse)
library(tidytext)
# ============================================
# --- Load the APNews data ---
# ============================================
# Read the data from the web
FetchedData <- readRDS(url("https://github.com/drkblake/Data/raw/refs/heads/main/APNews.rds"))
# Save the data on your computer
saveRDS(FetchedData, file = "APNews.rds")
# remove the downloaded data from the environment
rm (FetchedData)
APNews <- readRDS("APNews.rds")
# ============================================
# --- Flag Topic1-related stories ---
# ============================================
# --- Define Topic1 phrases ---
phrases <- c(
"Immigrant Arrest",
"ICE Raid",
"Immigration enforcement",
"deportation",
"detention center",
"DACA"
)
# --- Escape regex special characters ---
escaped_phrases <- str_replace_all(
phrases,
"([\\^$.|?*+()\\[\\]{}\\\\])",
"\\\\\\1"
)
# --- Build whole-word/phrase regex pattern ---
pattern <- paste0("\\b", escaped_phrases, "\\b", collapse = "|")
# --- Apply matching to flag Topic1 stories ---
APNews <- APNews %>%
mutate(
Full.Text.clean = str_squish(Full.Text), # normalize whitespace
Topic1 = if_else(
str_detect(Full.Text.clean, regex(pattern, ignore_case = TRUE)),
"Yes",
"No"
)
)
# ============================================
# --- Flag Topic2-related stories ---
# ============================================
# --- Define Topic2 phrases ---
phrases <- c(
"Immigrant right",
"asylum",
"Refugee Status",
"Asylum seeker",
"Temporary protected status"
)
# --- Escape regex special characters ---
escaped_phrases <- str_replace_all(
phrases,
"([\\^$.|?*+()\\[\\]{}\\\\])",
"\\\\\\1"
)
# --- Build whole-word/phrase regex pattern ---
pattern <- paste0("\\b", escaped_phrases, "\\b", collapse = "|")
# --- Apply matching to flag Topic2 stories ---
APNews <- APNews %>%
mutate(
Full.Text.clean = str_squish(Full.Text),
Topic2 = if_else(
str_detect(Full.Text.clean, regex(pattern, ignore_case = TRUE)),
"Yes",
"No"
)
)
# ============================================
# --- Visualize weekly counts of Topic1- and Topic2-related stories ---
# ============================================
# --- Load plotly if needed ---
if (!require("plotly")) install.packages("plotly")
library(plotly)
# --- Summarize weekly counts for Topic1 = "Yes" ---
Topic1_weekly <- APNews %>%
filter(Topic1 == "Yes") %>%
group_by(Week) %>%
summarize(Count = n(), .groups = "drop") %>%
mutate(Topic = "Immigration Arrest") # Note custom Topic1 label
# --- Summarize weekly counts for Topic2 = "Yes" ---
Topic2_weekly <- APNews %>%
filter(Topic2 == "Yes") %>%
group_by(Week) %>%
summarize(Count = n(), .groups = "drop") %>%
mutate(Topic = "Immigration Rights") # Note custom Topic2 label
# --- Combine both summaries into one data frame ---
Weekly_counts <- bind_rows(Topic2_weekly, Topic1_weekly)
# --- Fill in missing combinations with zero counts ---
Weekly_counts <- Weekly_counts %>%
tidyr::complete(
Topic,
Week = full_seq(range(Week), 1), # generate all week numbers
fill = list(Count = 0)
) %>%
arrange(Topic, Week)
# --- Create interactive plotly line chart ---
AS1 <- plot_ly(
data = Weekly_counts,
x = ~Week,
y = ~Count,
color = ~Topic,
colors = c("steelblue", "firebrick"),
type = "scatter",
mode = "lines+markers",
line = list(width = 2),
marker = list(size = 6)
) %>%
layout(
title = "Weekly Counts of Topic1- and Topic2-Related AP News Articles",
xaxis = list(
title = "Week Number (starting with Week 1 of 2025)",
dtick = 1
),
yaxis = list(title = "Number of Articles"),
legend = list(title = list(text = "Topic")),
hovermode = "x unified"
)
# ============================================
# --- Show the chart ---
# ============================================
AS1