An initial look …

Her’s a comparison of the weekly frequency of posts about the economy and immigration, by party, between Jan. 1, 2025 and Jan. 31, 2026:



Code:

See the phrases_topic1 and phrases_topic2 lists for the keywords and phrases that identified each topic.

# ============================================
# Congressional X Posts text analysis 
# (First-level agenda-setting theory version)
# ============================================

# ============================================
# --- Load required libraries ---
# ============================================

if (!require("tidyverse")) install.packages("tidyverse")
if (!require("tidytext")) install.packages("tidytext")

library(tidyverse)
library(tidytext)

# ============================================
# --- Load the data ---
# ============================================

Data <- readRDS("Latest119thData.rds")

# ============================================
# --- Add "Week" variable ---
# ============================================

Data <- Data %>%
  mutate(Date = as.Date(Date)) %>%
  mutate(
    WeekStart = lubridate::floor_date(Date, unit = "week", week_start = 1)
  )

first_week <- min(Data$WeekStart, na.rm = TRUE)

Data <- Data %>%
  mutate(Week = as.integer(difftime(WeekStart, first_week, units = "weeks")) + 1)

# ============================================
# --- Combine Democrats and independents ---
# ============================================

Data <- Data %>%
  mutate(
    party = case_when(
      party %in% c("Democrat", "Independent") ~ "Dem/Ind",
      party == "Republican" ~ "Rep",
      TRUE ~ "error"
    )
  )

# ============================================
# --- Define topic labels for graphs ---
# ============================================

Topic1Label <- "Immigration"
Topic2Label <- "Economy"

# ============================================
# --- Flag Topic1-related posts ---
# ============================================

phrases_topic1 <- c(
  "immigration",
  "immigrants",
  "immigrant",
  "asylum seekers",
  "refugee",
  "refugees",
  "alien",
  "aliens",
  "illegals",
  "border crossings",
  "cross the border",
  "crossed the border",
  "crossing the border",
  "the southern border",
  "border security",
  "secure the border",
  "secure the borders",
  "securing the border",
  "securing the borders",
  "secure border",
  "border security",
  "ICE",
  "I.C.E.",
  "CBP",
  "C.B.P.",
  "Renee Good",
  "Pretti"
)

escaped_phrases_topic1 <- str_replace_all(
  phrases_topic1,
  "([\\^$.|?*+()\\[\\]{}\\\\])",
  "\\\\\\1"
)

pattern_topic1 <- paste0("\\b", escaped_phrases_topic1, "\\b", collapse = "|")

Data <- Data %>%
  mutate(
    Full.Text.clean = str_squish(Full.Text),
    Topic1 = if_else(
      str_detect(Full.Text.clean, regex(pattern_topic1, ignore_case = TRUE)),
      "Yes",
      "No"
    )
  )

# ============================================
# --- Flag Topic2-related posts ---
# ============================================

phrases_topic2 <- c(
  "economy",
  "economic",
  "inflation",
  "tariff",
  "tariffs",
  "trade",
  "trading partners",
  "prices",
  "price of",
  "paying more for",
  "affordable",
  "affordability",
  "afford",
  "affording"
)

escaped_phrases_topic2 <- str_replace_all(
  phrases_topic2,
  "([\\^$.|?*+()\\[\\]{}\\\\])",
  "\\\\\\1"
)

pattern_topic2 <- paste0("\\b", escaped_phrases_topic2, "\\b", collapse = "|")

Data <- Data %>%
  mutate(
    Full.Text.clean = str_squish(Full.Text),
    Topic2 = if_else(
      str_detect(Full.Text.clean, regex(pattern_topic2, ignore_case = TRUE)),
      "Yes",
      "No"
    )
  )

# ============================================
# --- Visualize weekly counts (stacked by party) ---
# ============================================

if (!require("plotly")) install.packages("plotly")
library(plotly)

# --- Build Week -> WeekStart lookup so hover can show a date ---
WeekDates <- Data %>%
  distinct(Week, WeekStart) %>%
  arrange(Week)

# --- Summarize weekly counts by Party for Topic1 ---
Topic1_weekly_party <- Data %>%
  filter(party %in% c("Dem/Ind", "Rep"), Topic1 == "Yes") %>%
  group_by(party, Week) %>%
  summarize(Count = n(), .groups = "drop") %>%
  mutate(Topic = Topic1Label)

# --- Summarize weekly counts by Party for Topic2 ---
Topic2_weekly_party <- Data %>%
  filter(party %in% c("Dem/Ind", "Rep"), Topic2 == "Yes") %>%
  group_by(party, Week) %>%
  summarize(Count = n(), .groups = "drop") %>%
  mutate(Topic = Topic2Label)

# --- Combine Topic1 + Topic2 weekly counts ---
Weekly_counts_party <- bind_rows(Topic1_weekly_party, Topic2_weekly_party) %>%
  tidyr::complete(
    party,
    Topic,
    Week = full_seq(range(Data$Week, na.rm = TRUE), 1),
    fill = list(Count = 0)
  ) %>%
  left_join(WeekDates, by = "Week") %>%   # <-- add WeekStart date for hover
  arrange(party, Topic, Week)

# --- Hover template (shows week number + WeekStart date) ---
hover_tpl <- paste0(
  "<b>%{fullData.name}</b><br>",
  "Week: %{x}<br>",
  "Week start: %{customdata|%Y-%m-%d}<br>",
  "Count: %{y}<extra></extra>"
)

# --- Build party-specific plots ---
p_demind <- plot_ly(
  data = Weekly_counts_party %>% filter(party == "Dem/Ind"),
  x = ~Week,
  y = ~Count,
  color = ~Topic,
  colors = c("steelblue", "firebrick"),
  type = "scatter",
  mode = "lines+markers",
  line = list(width = 2),
  marker = list(size = 6),
  customdata = ~WeekStart,          # <-- what hover uses for the date
  hovertemplate = hover_tpl
) %>%
  layout(
    title = "",
    xaxis = list(title = ""),
    yaxis = list(title = "Number of Posts"),
    hovermode = "x unified",
    legend = list(title = list(text = "Topic"))
  )

p_rep <- plot_ly(
  data = Weekly_counts_party %>% filter(party == "Rep"),
  x = ~Week,
  y = ~Count,
  color = ~Topic,
  colors = c("steelblue", "firebrick"),
  type = "scatter",
  mode = "lines+markers",
  line = list(width = 2),
  marker = list(size = 6),
  customdata = ~WeekStart,
  hovertemplate = hover_tpl
) %>%
  layout(
    title = "",
    xaxis = list(
      title = "Week Number (Week 1 starts at first observed week in data)",
      dtick = 1
    ),
    yaxis = list(title = "Number of Posts"),
    hovermode = "x unified",
    legend = list(title = list(text = "Topic"))
  )

# --- Tile them vertically (stacked) with title + styled subtitle ---
AS_party <- subplot(
  p_demind, p_rep,
  nrows = 2,
  shareX = TRUE,
  shareY = TRUE,
  titleX = TRUE,
  titleY = TRUE
) %>%
  layout(
    title = list(
      text = paste0(
        "Weekly topic mentions by party",
        "<br><span style='font-size:0.80em; color:#6c757d;'>",
        "Top = Dem/Ind, Bottom = Rep",
        "</span>"
      )
    ),
    showlegend = TRUE
  )

# ============================================
# --- Show the chart ---
# ============================================

AS_party