---
title: 'Lab 11: Text-as-Data'
author: "PPOL 6803-03"
date: '2026-04-01'
output: html_document
---

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

library(dplyr)
library(tidytext)
library(ggplot2)
library(rvest)
library(ggwordcloud)
```

## Proj. 1: Working with Climate Change Tweets
### Load Data
```{r loaddata}
# A collection of tweets mentioning "climate change"
## (Apologies in advance if there is any... profanity)
tweets <- read.csv('https://github.com/apodkul/ppol6803_03/raw/main/Data/Climate_tweets.csv')
  
tweets %>% 
  glimpse()
```


### Work with Stop Words and Tokenization
```{r stopwords}
tidytext::stop_words %>% 
  head()

tidytext::stop_words %>% 
  dplyr::group_by(lexicon) %>%
  dplyr::summarize(n = n())

tweets %>% 
  mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>% 
  head()

tweets %>% 
  mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>%
  anti_join(stop_words) %>%
  head()

tweets <- tweets %>% 
  mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>%
  anti_join(stop_words) 

```

### Make a Word Cloud (if you have to)
```{r wordcloud}
# get word counts 
tweets %>% 
  dplyr::count(word) %>%
  arrange(desc(n)) %>% 
  head()

tweets %>% 
  dplyr::count(word) %>%
  arrange(desc(n)) %>%
  filter(n > 50) %>%
  ggplot(aes(label = word, size = n)) + 
  geom_text_wordcloud()

```


### Dictionary-based Sentiment Analysis
```{r sent}
tweets <- read.csv('https://github.com/apodkul/ppol6803_03/raw/main/Data/Climate_tweets.csv')

bing_words <- tidytext::get_sentiments('bing')

bing_words %>% 
  glimpse()


tweets %>% 
  mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>%
  anti_join(stop_words) %>%
  inner_join(bing_words) %>% 
  head()

tweets %>% 
  dplyr::mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>%
  anti_join(stop_words) %>%
  dplyr::inner_join(bing_words) %>% 
  dplyr::group_by(tweet_id, sentiment) %>%
  dplyr::summarize(n = n())%>% 
  head()

# change dictionary, may require download of `textdata` package
nrc_words <- tidytext::get_sentiments(lexicon = 'nrc')

tweets %>% 
  dplyr::mutate(tweet_id = 1:nrow(tweets)) %>%
  dplyr::select(tweet_id, text) %>%
  unnest_tokens(output = 'word', input = 'text') %>%
  anti_join(stop_words) %>%
  dplyr::inner_join(nrc_words) %>% 
  dplyr::group_by(tweet_id, sentiment) %>%
  dplyr::summarize(n = n())%>% 
  head()

```


## Proj. 2: Congressional Press Releases

### Get data
```{r}
# Goal: to scrape the latest press releases from AOC's congressional website

library(rvest)

all_links <- c()

for (page in 0:9) {
  url <- paste0("https://ocasio-cortez.house.gov/media/press-releases?page=", page)
  
  new_links <- read_html(url) %>%
    html_nodes("a") %>%
    html_attr("href") %>%
    .[stringr::str_detect(., "/media/press-releases/")] %>%
    unique()
  
  all_links <- unique(c(all_links, new_links)) %>%  na.omit()
}

list_of_links <- paste0("https://ocasio-cortez.house.gov", all_links) %>%
  unique()

output_data <- list()
for(i in 1:length(list_of_links)){
  tmp_var <- read_html(list_of_links[i]) %>%
      html_nodes('.evo-press-release__body') %>%
      html_text2()
  output_data[[i]] <- tmp_var
}

press_releases <- data.frame(id = 1:length(output_data), 
                             text = unlist(output_data))

#View(press_releases)

```


### Prep data for analysis 
```{r}
press_releases %>% 
  unnest_tokens(output = 'word', input = 'text') %>% 
  anti_join(stop_words, by = c('word' = 'word')) %>%
  dplyr::count(id, word) %>% 
  head()

press_releases <- press_releases %>% 
  unnest_tokens(output = 'word', input = 'text') %>% 
  anti_join(stop_words, by = c('word' = 'word')) %>%
  dplyr::count(id, word, name = 'count') 

pr_input <- press_releases %>%
  cast_dtm(id, word, count)

pr_input
```


### Estimate LDA Model (2 topics)
```{r}
library(topicmodels)
pr_lda <- LDA(pr_input, k = 2, 
              control = list(seed = 1789))
```


### Summarize and Visualize Model Outputs 
```{r}
pr_topics <- tidy(pr_lda, matrix = 'beta')
pr_topics

pr_top_terms <- pr_topics %>% 
  group_by(topic) %>%
  slice_max(beta, n = 10) %>%
  ungroup() %>%
  arrange(topic, -beta) %>%
  mutate(term = reorder(term, beta))

ggplot(pr_top_terms) + 
  geom_bar(aes(x = beta, y = term, fill = as.factor(topic)), 
           stat = 'identity') + 
  facet_wrap(~topic, scales = 'free')  + 
  theme(legend.position = 'none')

gg <- pr_topics %>%
  mutate(topic = paste0("topic", topic)) %>%
  tidyr::pivot_wider(names_from = topic, values_from = beta) %>% 
  filter(topic1 > .005 | topic2 > .005) %>%
  mutate(log_ratio = log2(topic2 / topic1)) %>%
  arrange(log_ratio) %>%
  mutate(term = reorder(term, log_ratio))

ggplot(gg) + 
  geom_bar(aes(x = log_ratio, y = term), 
           stat = 'identity')


# Get Gamma Terms 
gammas <- tidy(pr_lda, matrix = 'gamma')

gammas$document <- factor(gammas$document, levels = 1:100)
ggplot(gammas) + 
  geom_bar(aes(x = topic, y = gamma), stat = 'identity') + 
  facet_wrap(~document)

```
