---
title: "Trump vs. Harris Debate Analysis"
output:
  html_document: default
  pdf_document: default
  word_document: default
date: "2024-09-15"
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

## The attempt here is to produce a sentiment analysis of the debate.

We will use a [tidy](https://www.tidytextmining.com/sentiment) approach to sentiment analysis.

## Getting the data into the correct format and split between candidates.

```{r}
library(tidytext)
library(readr)
library(dplyr)
library(tidyr)
library(stringr)

# Read the transcript file
transcript <- read_lines("TrumpHarrisDebateTranscript.txt")

# Create a data frame from the transcript
transcript_df <- data.frame(line = 1:length(transcript), text = transcript, stringsAsFactors = FALSE)

# Extract speaker and comments
# this creates columns for speaker and the comment they made
transcript_df <- transcript_df %>%
  mutate(
    speaker = case_when(
      str_detect(text, "^VICE PRESIDENT KAMALA HARRIS:") ~ "HARRIS",
      str_detect(text, "^FORMER PRESIDENT DONALD TRUMP:") ~ "TRUMP",
      TRUE ~ NA_character_
    ),
    comment = case_when(
      str_detect(text, "^VICE PRESIDENT KAMALA HARRIS:|^FORMER PRESIDENT DONALD TRUMP:") 
        ~ str_remove(text, "^(VICE PRESIDENT KAMALA HARRIS:|^FORMER PRESIDENT DONALD TRUMP:)\\s*"),
      TRUE ~ NA_character_
    )
  ) %>%
  fill(speaker, .direction = "down") %>%
  filter(!is.na(comment))

# Separate the comments by each speaker
# unnest the words to be each their own line
# also remove stop words
harris_comments <- transcript_df %>%
  filter(speaker == "HARRIS") %>%
  select(comment) %>%
  ungroup() %>%
  unnest_tokens(word, comment) %>%
  anti_join(stop_words)

trump_comments <- transcript_df %>%
  filter(speaker == "TRUMP") %>%
  select(comment) %>%
  ungroup() %>%
  unnest_tokens(word, comment) %>%
  anti_join(stop_words)

```
## Connecting with Sentiment Lexicons

Let's do some inner joins with sentiment lexicons

```{r}
library(textdata)

# harris words joined with lexicon results
harris_nrc <- harris_comments %>%
  inner_join(get_sentiments("nrc"), relationship = "many-to-many")
harris_bing <- harris_comments %>%
  inner_join(get_sentiments("bing"), relationship = "many-to-many")
harris_afinn <- harris_comments %>%
  inner_join(get_sentiments("afinn"), relationship = "many-to-many")

# trump words joined with lexicon results
trump_nrc <- trump_comments %>%
  inner_join(get_sentiments("nrc"), relationship = "many-to-many")
trump_bing <- trump_comments %>%
  inner_join(get_sentiments("bing"), relationship = "many-to-many")
trump_afinn <- trump_comments %>%
  inner_join(get_sentiments("afinn"), relationship = "many-to-many")

```

## Normalizing for Afinn scores

Trump has 349 non-stop words with AFINN scores.
Harris has 277 non-stop words with AFINN scores.

We'll normalize to lengthen Harris' list to be same as Trump's.
Then plot both lines.

```{r}
library(zoo)
library(ggplot2)
library(ggsci)

# create new sequence of 349 points
new_length <- 349
new_index <- seq(1, nrow(harris_afinn),length.out = new_length)

# interpolate the values for harris
Harris <- data.frame(
  value = na.approx(harris_afinn$value, xout = new_index)
)

#new df of Trump AFINN values
Trump <- data.frame(trump_afinn$value)

timeline <- data.frame(seq(1,349))

combined_df <- cbind(timeline, Trump, Harris)
names(combined_df) <- c("time", "Trump", "Harris")

ggplot() +
  geom_line(data = combined_df, aes(x = time, y = cumsum(Trump), color = "Trump")) +
  geom_line(data = combined_df, aes(x = time, y = cumsum(Harris), color = "Harris")) +
  scale_color_manual(values = pal_lancet("lanonc")(2)[1:2]) +
  labs(title = "Comparison of language used in Harris vs. Trump debate",
       x = "Time (as measured by words)",
       y = "Cumulative Sentiment", 
       color = "Candidate") +
  theme(legend.position = "right") +
  theme_minimal()

# summary(combined_df$Trump)
# summary(combined_df$Harris)

```


## BING (positive vs negative counts)

Bar chart here, normalized to Trumps total word counts.
Trump has 305 words from BING, Harris has 272.

```{r}

# count the positive and negative sentiments
trumpBingCounts <- trump_bing %>% count(sentiment)
harrisBingCounts <- harris_bing %>% count(sentiment)
```

```{r}
# normalize or scale up Harris word counts to match Trumps
desired_total1 <- sum(trumpBingCounts$n) %>% as.numeric()
current_total1 <- sum(harrisBingCounts$n) %>% as.numeric()
scaling_factor_BING <- desired_total1 / current_total1 %>% as.numeric()
```

```{r}
# apply the scaling factor
harrisBingCounts <- harrisBingCounts %>%
  mutate(scaled_count = n * scaling_factor_BING)
```

```{r}
# add candidate column
# match format of two data.frames
trumpBingCounts <- data.frame(sentiment = trumpBingCounts$sentiment, 
                             count = trumpBingCounts$n,
                             candidate = rep("Trump", nrow(trumpBingCounts)))
harrisBingCounts <- data.frame(sentiment = harrisBingCounts$sentiment, 
                             count = harrisBingCounts$scaled_count,
                             candidate = rep("Harris", nrow(harrisBingCounts)))
```

```{r}
#combine datasets
Bing_Counts_Combined <- bind_rows(trumpBingCounts, harrisBingCounts)

#bar plot to compare candidates
ggplot(Bing_Counts_Combined, aes(x = candidate, y = count, fill = sentiment)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = pal_lancet("lanonc")(9)[9:8]) +
  labs(title = "Comparison of Two Candidates Bing Word Counts", x = "Candidate", y = "Count", fill = "Sentiment") +
  theme_minimal() 

```

## NRC analysis

This one is a little tougher because there are different categories.
Trump had 1573 words, Harris had 1393 words.

```{r}

# count the positive and negative sentiments
trumpNRCCounts <- trump_nrc %>% count(sentiment)
harrisNRCCounts <- harris_nrc %>% count(sentiment)

# normalize, or in other words scale up Harris' counts to equal Trump's
# we need a scaling factor (desired total / current total)
```

```{r}
# create scaling factor
desired_total <- sum(trumpNRCCounts$n) %>% as.numeric()
current_total <- sum(harrisNRCCounts$n) %>% as.numeric()
scaling_factor_NRC <- desired_total / current_total %>% as.numeric()
```

```{r}
# apply scaling factor
harrisNRCCounts <- harrisNRCCounts %>%
  mutate(scaled_count = n * scaling_factor_NRC)
```

```{r}
# add candidate column
trumpNRCCounts <- data.frame(sentiment = trumpNRCCounts$sentiment, 
                             count = trumpNRCCounts$n,
                             candidate = rep("Trump", nrow(trumpNRCCounts)))
harrisNRCCounts <- data.frame(sentiment = harrisNRCCounts$sentiment, 
                             count = harrisNRCCounts$scaled_count,
                             candidate = rep("Harris", nrow(harrisNRCCounts)))

#combine datasets
NRC_Counts_Combined <- bind_rows(trumpNRCCounts, harrisNRCCounts) %>%
  filter(!(sentiment %in% c("positive", "negative")))
```

```{r}
#bar plot to compare candidates
ggplot(NRC_Counts_Combined, aes(x = reorder(sentiment,-count), y = count, fill = candidate)) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_fill_manual(values = pal_lancet("lanonc")(2)[1:2]) +
  labs(title = "Comparison of Two Candidates NRC Word Counts", x = "Emotions", y = "Count", fill = "Candidate") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))
  
```