############################################################
# STEP 1: Install and Load Packages
############################################################
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("httr2")) install.packages("httr2")
if (!require("lubridate")) install.packages("lubridate")
if (!require("kableExtra")) install.packages("kableExtra")
if (!require("plotly")) install.packages("plotly")
library(tidyverse)
library(httr2)
library(lubridate)
library(kableExtra)
library(plotly)
############################################################
# STEP 2: Verify Media Cloud API Key
############################################################
if (!nzchar(Sys.getenv("MEDIACLOUD_KEY"))) {
stop(
"No Media Cloud API key was found.\n",
"Please save your key to .Renviron first."
)
}
############################################################
# STEP 3: Define Two Topics
############################################################
topics <- c(
"Artificial Intelligence" = "\"artificial intelligence\"",
"Climate Change" = "\"climate change\""
)
############################################################
# STEP 4: Define the Date Range
############################################################
start_date <- "2026-01-01"
end_date <- "2026-09-01"
############################################################
# STEP 5: Create a Function to Download Daily Story Counts
############################################################
get_counts <- function(query) {
Sys.sleep(35)
response <-
request("https://search.mediacloud.org/api/search/count-over-time") |>
req_headers(Authorization = paste("Token", Sys.getenv("MEDIACLOUD_KEY"))) |>
req_url_query(
q = query,
start = start_date,
end = end_date,
platform = "onlinenews-mediacloud",
cs = 34412234
) |>
req_perform()
results <- response |> resp_body_json()
map_dfr(results$count_over_time$counts, as_tibble) |>
mutate(date = as.Date(date))
}
############################################################
# STEP 6: Download Data for Both Topics
############################################################
topic_data <-
imap_dfr(topics, function(search_query, topic_name) {
message("Downloading: ", topic_name)
get_counts(search_query) |> mutate(topic = topic_name)
})
############################################################
# STEP 7: Examine the Downloaded Data
############################################################
head(topic_data)
glimpse(topic_data)
############################################################
# STEP 8: Calculate Weekly Story Counts
############################################################
weekly_counts <-
topic_data |>
mutate(week = floor_date(date, unit = "week")) |>
group_by(topic, week) |>
summarise(stories = sum(count), .groups = "drop")
############################################################
# STEP 9: Display Weekly Counts
############################################################
weekly_counts |>
arrange(topic, week) |>
kbl(caption = "Weekly Media Cloud Story Counts") |>
kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
############################################################
# STEP 10: Summarize Total Coverage
############################################################
topic_summary <-
weekly_counts |>
group_by(topic) |>
summarise(
Total_Stories = sum(stories),
Weekly_Minimum = min(stories),
Weekly_Maximum = max(stories),
Weekly_Mean = round(mean(stories), 2),
.groups = "drop"
) |>
arrange(desc(Total_Stories))
Summary_Table <- topic_summary |>
kbl(caption = "Coverage Summary by Topic") |>
kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
Summary_Table
############################################################
# STEP 11: Create a Line Graph
############################################################
Line_Graph <- weekly_counts |>
ggplot(aes(x = week, y = stories, color = topic)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
labs(
title = "Weekly Media Coverage Volume",
subtitle = "Comparison of Two Topics",
x = "Week",
y = "Number of Stories",
color = "Topic"
) +
theme_minimal()
Line_Graph
############################################################
# STEP 12: Save Results as a CSV File
############################################################
write_csv(weekly_counts, "weekly_story_counts.csv")
############################################################
# STEP 13: Create an Interactive plotly Line Graph
############################################################
Plotly_Line <- weekly_counts |>
filter(
week >= as.Date(start_date),
week + 6 <= as.Date(end_date)
) |>
plot_ly(
x = ~week,
y = ~stories,
color = ~topic,
colors = "Set1",
type = "scatter",
mode = "lines+markers",
hovertemplate = paste0(
"<b>%{fullData.name}</b><br>",
"Stories: %{y:,}<br>",
"Week of: %{x|%b %d, %Y}",
"<extra></extra>"
)
) |>
layout(
title = "Weekly Media Coverage Volume",
hovermode = "x unified",
xaxis = list(title = "Week"),
yaxis = list(title = "Number of Stories", tickformat = ","),
legend = list(title = list(text = "Topic")),
margin = list(t = 80)
)
Plotly_Line