First-level agenda-setting theory predicts that issues and individuals receiving prominent media coverage are more likely to become prominent in the minds of audiences. Because media organizations have limited time, space, and resources, attention devoted to one topic or group may reduce attention available for another. As a result, issues, events, and public figures often compete with one another for prominence on the media agenda.
Drawing on first-level agenda-setting theory, this project will compare the media agenda prominence of professional male soccer players and professional female soccer players. Specifically, the analysis will compare the number of stories per week that MediaCloud’s United States National news collection published about selected internationally recognized male and female soccer players between October 5, 2025, and October 24, 2026.
The results will contribute to understanding whether sports media provide similar levels of attention to male and female athletes. Although both groups contain highly successful and widely recognized players, differences in coverage volume may reveal continuing disparities in media attention and visibility between men’s and women’s sports.
Average weekly coverage for professional male soccer players is predicted to be greater than the coverage for professional female soccer players.
Weekly coverage volume served as the dependent variable for the analysis. It was measured continuously as the number of stories published each week that matched a MediaCloud search query identifying either elite male soccer players or elite female soccer players.
The independent variable was player gender category, measured categorically as either male soccer players or female soccer players.
The figure and table below summarize weekly coverage volume for male and female soccer players during the period analyzed. Coverage patterns indicate how frequently each group appeared in U.S. national news and whether one group consistently received greater attention than the other.
If the summary table shows that male soccer players received more total stories and a higher average weekly story count, the findings would suggest that elite male athletes occupied a more prominent position on the media agenda than elite female athletes. Such a result would be consistent with longstanding research showing that male sports often receive greater media attention than female sports.
However, these results disproved the predicted hypothesis.
Soccer coverage male vs female
| topic | Total_Stories | Weekly_Minimum | Weekly_Maximum | Weekly_Median | Weekly_Mean | Weekly_SD |
|---|---|---|---|---|---|---|
| male soccer players | 33420 | 133 | 2946 | 384 | 607.64 | 629.49 |
| female soccer players | 9932 | 70 | 335 | 174 | 180.58 | 56.71 |
The analysis used a paired-samples t-test to assess whether, on average, the difference between each week’s coverage volume measures fell nonrandomly above or below zero. This box plot summarizes the distributions of the female soccer player weekly story counts (V1) and the male soccer player weekly story counts (V2):
According to the results, stories mentioning male soccer players outnumbered stories mentioning female soccer players by an average of 427 stories per week, with a standard deviation of 56.7 stories. The average difference reflected the overall tendency for male soccer players to receive more media coverage during the study period, while the variability in pair differences indicated that the size of the coverage gap fluctuated substantially from week to week.
The paired differences showed a non-normal distribution according to the Shapiro-Wilk normality test 0. With approximately 55 weekly observations, the paired-samples t-test was considered sufficiently robust to provide reliable results despite any minor departures from normality. The pair differences therefore provided an appropriate basis for evaluating whether weekly coverage volume differed between male and female soccer players.
The paired-samples t-test found that the average difference in weekly media coverage between male and female soccer players was statistically significant. The t value was 1.08, with an associated p value of 0.29. Thus, the hypothesis was not supported. The results suggest that, despite some weeks in which male soccer players received substantially more coverage than female soccer players, the overall weekly volume of stories about male and female soccer players was not meaningfully different across the study period. As a result, the analysis does not provide sufficient evidence to conclude that one group consistently received greater media attention than the other.
| Paired-Samples t-Test | |||||
| statistic | parameter | p.value | conf.low | conf.high | method |
|---|---|---|---|---|---|
| 5.0240 | 54 | 0.0000 | 256.6327 | 597.4764 | Paired t-test |
One possible explanation for fluctuations in coverage between male and female soccer players is the influence of major sporting events, tournament schedules, player transfers, injuries, and other high-profile news developments. During certain weeks, media attention may have shifted toward individual male players because of competitions such as the UEFA Champions League, domestic league races, or international tournaments, resulting in temporary increases in coverage volume. Likewise, notable performances, awards, or tournaments involving female players may have contributed to occasional increases in coverage of women’s soccer.
Notably, periods of increased coverage for one group often appeared to coincide with relatively lower coverage for the other group. Because news organizations have limited space, time, and attention, heightened focus on one set of athletes may reduce attention available for other sports topics. This pattern is consistent with agenda-setting theory, which suggests that media outlets influence the prominence of issues and individuals by allocating greater coverage to some topics than others. Even though the overall difference in coverage was not statistically significant, week-to-week fluctuations demonstrate how media attention can shift between men’s and women’s soccer based on current events and newsworthiness.
Here is the code that produced the analysis:
############################################################
# 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-05"
end_date <- "2026-10-24"
############################################################
############################################################
############################################################
# STEP 4: Define Search Queries
############################################################
male_soccer_query <-
'("Lionel Messi" OR Messi OR
"Kylian Mbappe" OR Mbappe OR
"Erling Haaland" OR Haaland OR
"Jude Bellingham" OR Bellingham OR
"Cristiano Ronaldo" OR Ronaldo)'
female_soccer_query <-
'("Alex Morgan" OR
"Aitana Bonmati" OR Bonmati OR
"Sophia Smith" OR
"Trinity Rodman" OR
"Sam Kerr" OR Kerr)'
#############################################################
# STEP 5: Create Topic Definitions
############################################################
topics <- c(
"male soccer players" = male_soccer_query,
"female soccer players" = female_soccer_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
weekly_counts_wide <-
weekly_counts %>%
mutate(
topic = make.names(topic)
) %>%
select(week, topic, stories) %>%
pivot_wider(
names_from = topic,
values_from = stories
)
# ============================================================
# Setup: Install and Load Required Packages
# ============================================================
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("plotly")) install.packages("plotly")
if (!require("gt")) install.packages("gt")
if (!require("gtExtras")) install.packages("gtExtras")
if (!require("broom")) install.packages("broom")
library(tidyverse)
library(plotly)
library(gt)
library(gtExtras)
library(broom)
options(scipen = 999)
# ============================================================
# Data Import
# ============================================================
mydata <- weekly_counts_wide
# Specify the two variables involved
mydata$V1 <- mydata$female.soccer.players
mydata$V2 <- mydata$male.soccer.players
# ============================================================
# Compute Pair Differences
# ============================================================
mydata$PairDifferences <- mydata$V2 - mydata$V1
# ============================================================
# Interactive Histogram of Pair Differences
# ============================================================
hist_plot <- plot_ly(
data = mydata,
x = ~PairDifferences,
type = "histogram",
marker = list(color = "#1f78b4", line = list(color = "black", width = 1))
) %>%
layout(
title = "Distribution of Pair Differences",
xaxis = list(title = "Pair Differences"),
yaxis = list(title = "Count"),
shapes = list(
list(
type = "line",
x0 = mean(mydata$PairDifferences, na.rm = TRUE),
x1 = mean(mydata$PairDifferences, na.rm = TRUE),
y0 = 0,
y1 = max(table(mydata$PairDifferences)),
line = list(color = "red", dash = "dash")
)
)
)
# ============================================================
# Descriptive Statistics
# ============================================================
desc_stats <- mydata %>%
summarise(
count = n(),
mean = mean(PairDifferences, na.rm = TRUE),
sd = sd(PairDifferences, na.rm = TRUE),
min = min(PairDifferences, na.rm = TRUE),
max = max(PairDifferences, na.rm = TRUE)
)
desc_table <- desc_stats %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Descriptive Statistics: Pair Differences") %>%
fmt_number(columns = where(is.numeric), decimals = 3)
# ============================================================
# Normality Test (Shapiro-Wilk)
# ============================================================
shapiro_res <- shapiro.test(mydata$PairDifferences)
shapiro_table <- tidy(shapiro_res) %>%
select(statistic, p.value, method) %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Normality Test (Shapiro-Wilk)") %>%
fmt_number(columns = c(statistic, p.value), decimals = 4) %>%
tab_source_note(
source_note = "If the P.VALUE is 0.05 or less, the number of pairs is fewer than 40, and the distribution of pair differences shows obvious non-normality or outliers, consider using the Wilcoxon Signed Rank Test results instead of the Paired-Samples t-Test results."
)
# ============================================================
# Reshape Data for Repeated-Measures Plot
# ============================================================
df_long <- mydata %>%
pivot_longer(cols = c(V1, V2),
names_to = "Measure",
values_to = "Value")
# ============================================================
# Repeated-Measures Boxplot (Interactive, with Means)
# ============================================================
group_means <- df_long %>%
group_by(Measure) %>%
summarise(mean_value = mean(Value), .groups = "drop")
boxplot_measures <- plot_ly() %>%
add_trace(
data = df_long,
x = ~Measure, y = ~Value,
type = "box",
boxpoints = "outliers",
marker = list(color = "red", size = 4),
line = list(color = "black"),
fillcolor = "royalblue",
name = ""
) %>%
add_trace(
data = group_means,
x = ~Measure, y = ~mean_value,
type = "scatter", mode = "markers",
marker = list(
symbol = "diamond", size = 9,
color = "black", line = list(color = "white", width = 1)
),
text = ~paste0("Mean = ", round(mean_value, 2)),
hoverinfo = "text",
name = "Group Mean"
) %>%
layout(
title = "Boxplot of Repeated Measures (V1 vs V2) with Means",
xaxis = list(title = "Measure"),
yaxis = list(title = "Value"),
showlegend = FALSE
)
# ============================================================
# Parametric Test (Paired-Samples t-Test)
# ============================================================
t_res <- t.test(mydata$V2, mydata$V1, paired = TRUE)
t_table <- tidy(t_res) %>%
select(statistic, parameter, p.value, conf.low, conf.high, method) %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Paired-Samples t-Test") %>%
fmt_number(columns = c(statistic, p.value, conf.low, conf.high), decimals = 4)
t_summary <- mydata %>%
select(V1, V2) %>%
summarise_all(list(Mean = mean, SD = sd)) %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Group Means and SDs (t-Test)") %>%
fmt_number(columns = everything(), decimals = 3)
# ============================================================
# Nonparametric Test (Wilcoxon Signed Rank)
# ============================================================
wilcox_res <- wilcox.test(mydata$V1, mydata$V2, paired = TRUE,
exact = FALSE)
wilcox_table <- tidy(wilcox_res) %>%
select(statistic, p.value, method) %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Wilcoxon Signed Rank Test") %>%
fmt_number(columns = c(statistic, p.value), decimals = 4)
wilcox_summary <- mydata %>%
select(V1, V2) %>%
summarise_all(list(Mean = mean, SD = sd)) %>%
gt() %>%
gt_theme_538() %>%
tab_header(title = "Group Means and SDs (Wilcoxon)") %>%
fmt_number(columns = everything(), decimals = 3)
# ============================================================
# Results Summary (in specified order)
# ============================================================
hist_plot
desc_table
shapiro_table
boxplot_measures
t_table
t_summary
wilcox_table
wilcox_summary
weekly_counts_wide <-
weekly_counts %>%
mutate(
topic = make.names(topic)
) %>%
select(week, topic, stories) %>%
pivot_wider(
names_from = topic,
values_from = stories
)
# ============================================================
# Data Import
# ============================================================
mydata <- weekly_counts_wide
# Specify the two variables involved
mydata$V1 <- mydata$female.soccer.players
mydata$V2 <- mydata$male.soccer.players
# ============================================================