According to McCombs and Shaw, agenda-setting theory posits that issues that receive greater attention in the news media often become more prominent in the public mind. In first-level agenda-setting, topics compete for salience in the media agenda, where differences in media attention often shape what audiences perceive as important issues. Therefore, examining differences in coverage volume between vaccine-preventable outbreaks and food recalls provides a means of comparing topic salience in the media agenda.
Using the phenomenon as a guide, my project will compare the media agenda salience of two issues: vaccine-preventable disease outbreaks and food recalls and contamination events. Specifically, this analysis will compare the number of stories per week that MediaCloud.org’s United States - National news archive collected for each topic over one year, from October 19, 2025, through October 18, 2026.
The results will enhance understanding of how two human health issues compete for attention in the media agenda.
Between October 2025 and October 2026, average weekly coverage volume differed across vaccine-preventable disease outbreaks and food recall and contamination events.
The independent variable was public health issue type, categorized as either vaccine-preventable disease outbreaks or food recalls and contamination events. The dependent variable was media salience, operationalized as the weekly number of news stories retrieved via MediaCloud.org queries for each issue. The weeks analyzed were October 19, 2025, through October 18, 2026.
Stories about the vaccine-preventable disease outbreaks were operationalized with the following MediaCloud query:
vaccine_query <- “((measles OR mumps OR pertussis OR whooping cough) AND (outbreak* OR cases OR vaccine* OR infection* OR transmission OR MMR OR measles vaccine))”
Stories about the food recalls and contamination events were operationalized with the following MediaCloud query:
food_query <- “((cyclospora OR salmonella OR listeria OR e.coli) AND (food recall* OR recalled food OR recall OR recalls OR contamination OR foodborne illness OR food safety OR produce))”
Eventually, I will use a paired-samples t-test to assess the statistical significance of the difference in coverage volume between the two topics.
The figure and table below display each topic’s weekly coverage volume across the period analyzed. Food recalls received substantially more media attention than vaccine-preventable disease outbreaks. Food recall coverage surged in July and August 2026, reaching its highest level during the study period. Vaccine-preventable disease outbreak coverage remained relatively low and stable, with a notable spike occurring in early January 2026. Overall, food recalls and contamination events received more than twice as much coverage as vaccine-preventable disease outbreaks. These findings suggest that food recalls occupied a more prominent position on the media agenda during the study period.
| topic | Total_Stories | Weekly_Minimum | Weekly_Maximum | Weekly_Median | Weekly_Mean | Weekly_SD |
|---|---|---|---|---|---|---|
| Food recall and contamination events | 3515 | 1 | 465 | 28 | 66.32 | 97.65 |
| Vaccine-preventable disease outbreaks | 1407 | 1 | 121 | 23 | 26.55 | 18.26 |
The substantial increase in food recall and contamination coverage from July through early August 2026 appears to coincide with widespread media attention surrounding the Cyclospora outbreak linked to Taylor Farms.
############################################################
# STEP 1: Install and Load Required Packages
############################################################
required_packages <- c(
"tidyverse",
"httr2",
"lubridate",
"plotly",
"knitr",
"kableExtra"
)
for (pkg in required_packages) {
if (!requireNamespace(pkg, quietly = TRUE)) {
install.packages(pkg)
}
}
library(tidyverse)
library(httr2)
library(lubridate)
library(plotly)
library(knitr)
library(kableExtra)
############################################################
# STEP 2: Verify Media Cloud API Key
############################################################
if (!nzchar(Sys.getenv("MEDIACLOUD_KEY"))) {
stop(
"No Media Cloud API key was found.\n",
"Run the setup section once,\n",
"then restart R and try again."
)
}
mc_key <- Sys.getenv("MEDIACLOUD_KEY")
############################################################
# STEP 3: Define the Date Range
############################################################
start_date <- "2025-10-19"
end_date <- "2026-10-18"
############################################################
# STEP 4: Define Search Queries
############################################################
vaccine_query <-
"((measles OR mumps OR pertussis OR whooping cough) AND
(outbreak* OR cases OR vaccine* OR infection* OR transmission OR MMR OR measles vaccine))"
food_query <-
"((cyclospora OR salmonella OR listeria OR e.coli)
AND (food recall* OR recalled food OR recall OR recalls OR contamination OR foodborne illness OR food safety OR produce))"
############################################################
# STEP 5: Create Topic Definitions
############################################################
topics <- c(
"Vaccine-preventable disease outbreaks" = vaccine_query,
"Food recall and contamination events" = food_query
)
############################################################
# STEP 6: Create a Function to Retrieve Daily
# Story Counts
############################################################
mc_counts_over_time <- function(
query,
start_date,
end_date,
collection_id = 34412234
) {
resp <-
request(
"https://search.mediacloud.org/api/search/count-over-time"
) |>
req_headers(
Authorization = paste("Token", mc_key)
) |>
req_url_query(
q = query,
start = start_date,
end = end_date,
platform = "onlinenews-mediacloud",
cs = collection_id
) |>
req_perform()
results <- resp |>
resp_body_json()
map_dfr(
results$count_over_time$counts,
as_tibble
) |>
mutate(
date = as.Date(date)
)
}
############################################################
# STEP 7: Download Daily Counts for All Topics
############################################################
topic_data <-
imap_dfr(
topics,
function(search_string, topic_name) {
message(
"Downloading: ",
topic_name
)
results <-
mc_counts_over_time(
query = search_string,
start_date = start_date,
end_date = end_date
)
Sys.sleep(35)
results |>
mutate(
topic = topic_name
)
}
)
############################################################
# STEP 8: Examine the Downloaded Daily Data
############################################################
head(topic_data)
glimpse(topic_data)
############################################################
# STEP 9: Convert Daily Counts to Weekly Counts
############################################################
weekly_counts <-
topic_data |>
mutate(
week = floor_date(
date,
unit = "week"
)
) |>
group_by(
topic,
week
) |>
summarise(
stories = sum(count),
.groups = "drop"
)
############################################################
# STEP 10: Examine Weekly Counts
############################################################
weekly_counts
############################################################
# STEP 11: Summarize Coverage by Topic
############################################################
topic_summary <-
weekly_counts |>
group_by(topic) |>
summarise(
Total_Stories = sum(stories),
Weekly_Minimum = min(stories),
Weekly_Maximum = max(stories),
Weekly_Median = median(stories),
Weekly_Mean = round(
mean(stories),
2
),
Weekly_SD = round(
sd(stories),
2
),
.groups = "drop"
) |>
arrange(
desc(Total_Stories)
)
Table <-
topic_summary |>
kbl(
caption =
"Media Cloud Topic Summary Statistics",
align = "lrrrrrr"
) |>
kable_styling(
full_width = FALSE,
bootstrap_options = c(
"striped",
"hover",
"condensed"
)
)
Table
############################################################
# STEP 12: Create an Interactive Plotly Graph
############################################################
weekly_counts <- weekly_counts |>
mutate(
stories_formatted = formatC(
stories,
format = "d",
big.mark = ","
)
)
Graph <- plot_ly(
data = weekly_counts,
x = ~week,
y = ~stories,
color = ~topic,
colors = "Set1",
type = "scatter",
mode = "lines+markers",
customdata = ~topic,
text = ~stories_formatted,
hovertemplate =
paste(
"%{customdata}
",
"Week: %{x|%Y-%m-%d}
",
"Stories: %{text}
",
""
)
) |>
layout(
title =
"Weekly U.S. Coverage Volume",
hovermode = "x unified",
xaxis = list(
title = "Week"
),
yaxis = list(
title = "Weekly Story Count",
separatethousands = TRUE
)
)
Graph