Rationale

First-level agenda-setting theory looks at how the media influences what people think is most important. The idea is that when certain topics get more attention in the news, they also become more important in people’s minds. Since news outlets only have so much time and space, some issues end up competing for coverage. When one topic gets a lot of attention, another might fade into the background for a while.

For this project, I’ll be comparing how often APNews.com covered the war in Gaza and the war in Ukraine during 2025. Both are major world events that involve ongoing conflict and political tension, but they don’t always share the spotlight. I want to see how much coverage each one gets and if there are times when a rise in one means a drop in the other.

This will help show how two big issues can shift in importance on the media’s agenda, and how that might affect what audiences focus on.

Hypothesis

APNews.com gave different levels of attention to the wars in Gaza and Ukraine during the first nine months of 2025.

Variables & method

The dependent variable will be the number of stories APNews.com published each week about each war. The independent variable will be the story topic, which will either be “Gaza” or “Ukraine.” To find the stories, I’ll use keywords that clearly connect to each topic. For Gaza: “Gaza,” “Israel,” “Hamas,” “Israeli hostages,” and “Palestinian refugees.” For Ukraine: “Ukraine,” “Russia,” “Vladimir Putin,” and “Volodymyr Zelenskyy.”

After collecting the weekly totals, I’ll compare the two topics using a paired-samples t-test to see if the difference in coverage is statistically significant.

Results & discussion

The data shows that APNews.com covered Gaza more heavily than Ukraine for most weeks of 2025.

The biggest increase in Gaza coverage happened around Week 25 (June 16–22), when there were 182 stories. That week focused on direct military attacks between Israel and Iran, which likely drove the spike. During the same week, Ukraine coverage dropped to 40 stories.

Ukraine coverage reached its highest point in Week 9 (Feb. 24–March 3), with 108 stories. Many of those focused on the third anniversary of Russia’s invasion and on reports about President Trump meeting with Ukrainian President Zelenskyy. During that time, Gaza coverage was noticeably lower.

Overall, the results suggest that when one war gained attention, the other lost some. This back-and-forth pattern fits what first-level agenda-setting theory predicts about how issues compete for attention in the media.

Code:

# ============================================
# --- 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(
  "Gaza",
  "Israel",
  "Hamas",
  "Israeli hostages",
  "Palestinian refugees"
)

# --- 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(
  "Russia",
  "Ukraine",
  "Vladimir Putin",
  "Volodymyr Zelenskyy"
)

# --- 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 = "Gaza") # 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 = "Ukraine") # 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