For this assignment, I used text mining techniques in R to analyze two-word phrases, also known as bigrams, found in news headlines from the Trump_story_headlines dataset. I separated the headlines into two groups: headlines containing the word “Trump” and headlines not containing the word “Trump.” After cleaning the text and removing common stop words, I generated bigrams and created visualizations to identify the most frequently occurring phrases over time. The results showed that certain phrases appeared repeatedly, revealing common topics covered by news organizations. In the Trump-related headlines, phrases often focused on political events, legal issues, court proceedings, elections, and government actions. These recurring bigrams suggested that media coverage of Trump was centered largely on political controversy and national policy discussions.
The ridgeline plots helped visualize how the popularity of different phrases changed over time. By looking at the peaks and valleys in the graphs, it became easier to identify when specific topics received increased media attention. The non-Trump headlines highlighted a broader variety of topics, while the Trump-related headlines were more concentrated around a smaller number of recurring themes. This suggests that Trump remained a highly visible figure in the news cycle and that many headlines focused on similar events or issues.
Artificial intelligence played a significant role in completing this assignment. I used AI to help develop and troubleshoot the R code needed for creating bigrams, cleaning text, calculating frequencies, and building ridgeline plots. AI assistance saved time, helped resolve coding errors, and provided alternative visualization approaches. However, I still had to test, revise, and interpret the results myself. Overall, AI served as a helpful tool that improved efficiency while allowing me to better understand text mining and data visualization concepts.
############################################################
# MC 6600: Donald Trump Headlines Bigram Analysis
# Comparing Trump Headlines vs Other Headlines
############################################################
# Step 1: Load Packages ----
if (!require(tidyverse)) {
install.packages("tidyverse")
library(tidyverse)
}
if (!require(tidytext)) {
install.packages("tidytext")
library(tidytext)
}
# Step 2: Load Data ----
Trump_story_headlines <- readRDS(
"Trump_story_headlines.rds"
)
# Step 3: Create Groups ----
headlines <- Trump_story_headlines %>%
mutate(
headline_group = if_else(
str_detect(
tolower(title),
"trump"
),
"Trump Headlines",
"Other Headlines"
)
)
# Step 4: Create Bigrams ----
headline_bigrams <- headlines %>%
unnest_tokens(
bigram,
title,
token = "ngrams",
n = 2
)
# Step 5: Split Bigrams ----
bigrams_separated <- headline_bigrams %>%
separate(
bigram,
into = c("word1", "word2"),
sep = " "
)
# Step 6: Remove Stop Words ----
data("stop_words")
bigrams_clean <- bigrams_separated %>%
filter(
!word1 %in% stop_words$word,
!word2 %in% stop_words$word
)
# Step 7: Rebuild Bigrams ----
bigrams_final <- bigrams_clean %>%
unite(
bigram,
word1,
word2,
sep = " "
)
# Step 8: Count Bigrams by Group ----
group_bigram_counts <- bigrams_final %>%
count(
headline_group,
bigram,
sort = TRUE
)
# Step 9: Top 15 Bigrams Per Group ----
top_bigram_chart_data <- group_bigram_counts %>%
group_by(headline_group) %>%
slice_max(
n,
n = 15
) %>%
ungroup()
# Step 10: Create Chart ----
bigram_chart <- ggplot(
top_bigram_chart_data,
aes(
x = reorder_within(
bigram,
n,
headline_group
),
y = n,
fill = headline_group
)
) +
geom_col(
show.legend = FALSE
) +
geom_text(
aes(label = n),
hjust = -0.1,
size = 3
) +
coord_flip() +
scale_x_reordered() +
facet_wrap(
~headline_group,
ncol = 1,
scales = "free_y"
) +
scale_fill_manual(
values = c(
"Trump Headlines" = "firebrick",
"Other Headlines" = "steelblue"
)
) +
scale_y_continuous(
expand = expansion(
mult = c(0, .10)
)
) +
labs(
title = "Most Common Two-Word Phrases in Headlines",
subtitle = "Trump Headlines Compared with Other Headlines",
x = "Bigram",
y = "Occurrences"
) +
theme_minimal() +
theme(
strip.text = element_text(
face = "bold"
)
)
bigram_chart
############################################################
# MC 6600
# Donald Trump Headlines Bigram Ridgeline Plot
############################################################
# Step 1: Load Packages ----
library(tidyverse)
library(tidytext)
library(lubridate)
library(ggridges)
# Step 2: Load Data ----
Trump_story_headlines <- readRDS(
"Trump_story_headlines.rds"
)
# Step 3: Analysis Settings ----
n_size <- 2
top_n_phrases <- 20
data("stop_words")
# Step 4: Keep Headlines Containing Trump ----
text_data <- Trump_story_headlines %>%
filter(
str_detect(
tolower(title),
"trump"
)
) %>%
mutate(
publish_date = as.Date(publish_date),
WeekStart = floor_date(
publish_date,
unit = "week",
week_start = 1
)
)
# Step 5: Create Bigrams ----
bigrams <- text_data %>%
unnest_tokens(
bigram,
title,
token = "ngrams",
n = n_size
)
# Step 6: Split Words ----
bigrams_clean <- bigrams %>%
separate(
bigram,
into = c(
"word1",
"word2"
),
sep = " "
) %>%
filter(
!word1 %in% stop_words$word,
!word2 %in% stop_words$word
)
# Optional:
# Remove trump/donald so better phrases emerge
bigrams_clean <- bigrams_clean %>%
filter(
!word1 %in% c("trump", "donald"),
!word2 %in% c("trump", "donald")
)
# Step 7: Recombine Bigrams ----
bigrams_final <- bigrams_clean %>%
unite(
bigram,
word1,
word2,
sep = " "
)
# Step 8: Top Bigrams ----
top_bigrams <- bigrams_final %>%
count(
bigram,
sort = TRUE
) %>%
slice_max(
n,
n = top_n_phrases
)
# Step 9: Weekly Counts ----
weekly_bigram_counts <- bigrams_final %>%
semi_join(
top_bigrams,
by = "bigram"
) %>%
count(
bigram,
WeekStart,
name = "weekly_count"
)
# Step 10: Fill Missing Weeks ----
weekly_bigram_counts <- weekly_bigram_counts %>%
group_by(
bigram
) %>%
complete(
WeekStart = seq(
min(WeekStart),
max(WeekStart),
by = "week"
),
fill = list(
weekly_count = 0
)
) %>%
ungroup()
# Step 11: Order Bigrams ----
bigram_order <- top_bigrams %>%
arrange(
desc(n)
) %>%
pull(
bigram
)
weekly_bigram_counts <- weekly_bigram_counts %>%
mutate(
bigram = factor(
bigram,
levels = rev(bigram_order)
)
)
# Step 12: Ridgeline Plot ----
bigram_ridgeline <- ggplot(
weekly_bigram_counts,
aes(
x = WeekStart,
y = weekly_count,
height = weekly_count,
group = bigram
)
) +
geom_ridgeline(
fill = "steelblue",
color = "white",
alpha = .85,
scale = 0.75,
min_height = 0
) +
facet_wrap(
~ bigram,
ncol = 1,
scales = "free_y",
strip.position = "right"
) +
labs(
title = "Weekly Frequency of Top Trump Headline Bigrams",
subtitle = "Most Frequently Used Two-Word Phrases Over Time",
x = "Week",
y = NULL
) +
theme_ridges() +
theme(
strip.text.y.right =
element_text(
size = 8,
angle = 0,
face = "bold"
),
axis.text.y =
element_blank(),
axis.ticks.y =
element_blank(),
panel.spacing =
unit(.15, "lines"),
legend.position = "none"
)
bigram_ridgeline
bigram_ridgeline
############################################################
# MC 6600
# Headlines NOT Containing Trump
# Bigram Ridgeline Plot
############################################################
library(tidyverse)
library(tidytext)
library(lubridate)
library(ggridges)
# Load Data ----
Trump_story_headlines <- readRDS(
"Trump_story_headlines.rds"
)
data("stop_words")
############################################################
# Create Dataset
############################################################
non_trump_headlines <- Trump_story_headlines %>%
filter(
!str_detect(
tolower(title),
"trump"
)
) %>%
mutate(
publish_date = as.Date(publish_date),
WeekStart = floor_date(
publish_date,
unit = "week",
week_start = 1
)
)
############################################################
# Create Bigrams
############################################################
non_trump_bigrams <- non_trump_headlines %>%
unnest_tokens(
bigram,
title,
token = "ngrams",
n = 2
)
############################################################
# Clean Bigrams
############################################################
non_trump_bigrams <- non_trump_bigrams %>%
separate(
bigram,
into = c(
"word1",
"word2"
),
sep = " "
) %>%
filter(
!word1 %in% stop_words$word
) %>%
filter(
!word2 %in% stop_words$word
) %>%
unite(
bigram,
word1,
word2,
sep = " "
)
############################################################
# Top Bigrams
############################################################
top_bigrams <- non_trump_bigrams %>%
count(
bigram,
sort = TRUE
) %>%
slice_head(
n = 12
)
############################################################
# Count Weekly Frequency
############################################################
weekly_bigram_counts <- non_trump_bigrams %>%
semi_join(
top_bigrams,
by = "bigram"
) %>%
count(
bigram,
WeekStart,
name = "frequency"
)
############################################################
# Fill Missing Weeks
############################################################
weekly_bigram_counts <- weekly_bigram_counts %>%
group_by(
bigram
) %>%
complete(
WeekStart = seq(
min(WeekStart),
max(WeekStart),
by = "week"
),
fill = list(
frequency = 0
)
) %>%
ungroup()
############################################################
# Plot
############################################################
non_trump_ridgeline <- ggplot(
weekly_bigram_counts,
aes(
x = WeekStart,
y = frequency,
height = frequency
)
) +
geom_ridgeline(
fill = "firebrick",
color = "white",
alpha = .80,
scale = 0.25,
min_height = 0
) +
facet_wrap(
~ bigram,
ncol = 1,
scales = "free_y",
strip.position = "right"
) +
labs(
title =
"Weekly Volume of Top Non-Trump Headline Bigrams",
subtitle =
"Most Frequently Used Two-Word Phrases",
x = "Week",
y = NULL
) +
theme_ridges() +
theme(
strip.text.y.right =
element_text(
size = 8,
angle = 0,
face = "bold"
),
axis.text.y =
element_blank(),
axis.ticks.y =
element_blank(),
panel.spacing =
unit(
.03,
"lines"
),
legend.position =
"none"
)
non_trump_ridgeline