library(shiny)
library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Load and preprocess data
emotional <- read.csv("emotionanalysis2.csv")  # Ensure this file exists

# Convert season and episode to numeric for proper ordering
emotional$seinfeld.season <- as.numeric(as.character(emotional$seinfeld.season))
emotional$seinfeld.episode <- as.numeric(as.character(emotional$seinfeld.episode))
emotional$office.season <- as.numeric(as.character(emotional$office.season))
emotional$office.episode <- as.numeric(as.character(emotional$office.episode))
emotional$modern.season <- as.numeric(as.character(emotional$modern.season))
emotional$modern.episode <- as.numeric(as.character(emotional$modern.episode))

# Create a combined dataset for each show
seinfeld_data <- emotional %>%
  select(seinfeld.season, seinfeld.episode, seinfeld.score, seinfeld.emotion) %>%
  rename(season = seinfeld.season, episode = seinfeld.episode, score = seinfeld.score, emotion = seinfeld.emotion) %>%
  mutate(show = "Seinfeld")

office_data <- emotional %>%
  select(office.season, office.episode, office.score, office.emotion) %>%
  rename(season = office.season, episode = office.episode, score = office.score, emotion = office.emotion) %>%
  mutate(show = "The Office")

modern_data <- emotional %>%
  select(modern.season, modern.episode, modern.score, modern.emotion) %>%
  rename(season = modern.season, episode = modern.episode, score = modern.score, emotion = modern.emotion) %>%
  mutate(show = "Modern Family")

# Combine all datasets
combined_data <- bind_rows(seinfeld_data, office_data, modern_data) %>%
  filter(!is.na(season) & !is.na(episode))  # Remove NA values

# Define UI
ui <- fluidPage(
  titlePanel("TV Show Sentiment Analysis: Seinfeld, The Office & Modern Family"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("selectedSeason", "Select Season:",
                  choices = sort(unique(combined_data$season))),
      
      sliderInput("episodeRange", "Select Episode Range:",
                  min = 1, max = 10, value = c(1, 10), step = 1),
      
      radioButtons("showFilter", "Select Show:", 
                   choices = c("All", "Seinfeld", "The Office", "Modern Family"), 
                   selected = "All"),
      
      checkboxGroupInput("emotionFilter", "Select Emotions to Display:",
                         choices = unique(combined_data$emotion),
                         selected = unique(combined_data$emotion)),  # Default: all selected
      
      actionButton("reset", "Reset Filters")
    ),
    
    mainPanel(
      plotOutput("episodePlot", height = "600px")
    )
  )
)

# Define Server Logic
server <- function(input, output, session) {
  
  # Update episode range dynamically based on selected season
  observe({
    season_data <- combined_data %>% filter(season == input$selectedSeason)
    
    updateSliderInput(session, "episodeRange",
                      min = min(season_data$episode, na.rm = TRUE),
                      max = max(season_data$episode, na.rm = TRUE),
                      value = c(min(season_data$episode, na.rm = TRUE), max(season_data$episode, na.rm = TRUE)))
  })
  
  # Reactive dataset filtered by season, episode range, show, and emotions
  filtered_data <- reactive({
    data <- combined_data %>%
      filter(season == input$selectedSeason & 
             episode >= input$episodeRange[1] & 
             episode <= input$episodeRange[2] & 
             emotion %in% input$emotionFilter)  # Filter by selected emotions
    
    # Apply show filtering based on user selection
    if (input$showFilter == "Seinfeld") {
      data <- data %>% filter(show == "Seinfeld")
    } else if (input$showFilter == "The Office") {
      data <- data %>% filter(show == "The Office")
    } else if (input$showFilter == "Modern Family") {
      data <- data %>% filter(show == "Modern Family")
    }
    
    return(data)
  })
  
  # Generate the ggplot
  output$episodePlot <- renderPlot({
    ggplot(filtered_data(), aes(x = episode, y = score, color = emotion, shape = show, group = interaction(show, emotion))) +
      geom_point(size = 3, alpha = 0.7) +
      geom_line(aes(linetype = show), size = 1) +
      labs(title = paste("Seinfeld vs. The Office vs. Modern Family: Score by Episode - Season", input$selectedSeason),
           x = "Episode",
           y = "Score",
           color = "Emotion",
           shape = "Show",
           linetype = "Show") +
      theme_minimal()
  })
  
  # Reset button action
  observeEvent(input$reset, {
    season_data <- combined_data %>% filter(season == input$selectedSeason)
    
    updateSliderInput(session, "episodeRange",
                      value = c(min(season_data$episode, na.rm = TRUE), max(season_data$episode, na.rm = TRUE)))
    
    updateRadioButtons(session, "showFilter", selected = "All")
    
    updateCheckboxGroupInput(session, "emotionFilter",
                             selected = unique(combined_data$emotion))  # Reset emotions to all selected
  })
}

# Run the Shiny app
shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents

VISUALIZATION 2

library(shiny)
library(ggplot2)
library(dplyr)
library(tidyr)

# Load and preprocess data
sentiment <- read.csv("all_sentiment.csv")  # Ensure this file exists

# Convert season and episode for Seinfeld & The Office
sentiment$seinfeld.season <- as.numeric(as.character(sentiment$seinfeld.season))
sentiment$seinfeld.season.episode <- as.numeric(as.character(sentiment$seinfeld.season.episode))
sentiment$office.season <- as.numeric(as.character(sentiment$office.season))
sentiment$office.episode <- as.numeric(as.character(sentiment$office.episode))

# **Fix Modern Family's season.episode format (e.g., 1.01 → S1E1, 2.05 → S2E5)**
sentiment <- sentiment %>%
  mutate(
    modern.season = floor(modern.season.episode),  # Extract season as integer
    modern.episode = round((modern.season.episode - modern.season) * 100)  # Extract episode number
  )

# Create a combined dataset using TextBlob sentiment
seinfeld_data <- sentiment %>%
  select(seinfeld.season, seinfeld.season.episode, seinfeld.average.sentiment) %>%
  rename(season = seinfeld.season, episode = seinfeld.season.episode, sentiment = seinfeld.average.sentiment) %>%
  mutate(show = "Seinfeld")

office_data <- sentiment %>%
  select(office.season, office.episode, office.modern.average.textblob.sentiment) %>%
  rename(season = office.season, episode = office.episode, sentiment = office.modern.average.textblob.sentiment) %>%
  mutate(show = "The Office")

modern_data <- sentiment %>%
  select(modern.season, modern.episode, modern.average.textblob.sentiment) %>%
  rename(season = modern.season, episode = modern.episode, sentiment = modern.average.textblob.sentiment) %>%
  mutate(show = "Modern Family")

# Combine and clean dataset
combined_data <- bind_rows(seinfeld_data, office_data, modern_data) %>%
  filter(!is.na(season) & !is.na(episode) & !is.na(sentiment))  # Remove NA values

# Define UI
ui <- fluidPage(
  titlePanel("TV Show Sentiment Analysis: Seinfeld, The Office & Modern Family"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("selectedSeason", "Select Season:",
                  choices = sort(unique(combined_data$season))),
      
      sliderInput("episodeRange", "Select Episode Range:",
                  min = 1, max = 10, value = c(1, 10), step = 1),
      
      radioButtons("showFilter", "Select Show:", 
                   choices = c("All", "Seinfeld", "The Office", "Modern Family"), 
                   selected = "All"),
      
      actionButton("reset", "Reset Filters")
    ),
    
    mainPanel(
      plotOutput("sentimentPlot", height = "600px")
    )
  )
)

# Define Server Logic
server <- function(input, output, session) {
  
  # Update episode range dynamically based on selected season
  observe({
    season_data <- combined_data %>% filter(season == input$selectedSeason)
    
    updateSliderInput(session, "episodeRange",
                      min = min(season_data$episode, na.rm = TRUE),
                      max = max(season_data$episode, na.rm = TRUE),
                      value = c(min(season_data$episode, na.rm = TRUE), max(season_data$episode, na.rm = TRUE)))
  })
  
  # Reactive dataset filtered by season, episode range, and selected show
  filtered_data <- reactive({
    data <- combined_data %>%
      filter(season == input$selectedSeason & 
             episode >= input$episodeRange[1] & 
             episode <= input$episodeRange[2])
    
    # Apply show filtering based on user selection
    if (input$showFilter == "Seinfeld") {
      data <- data %>% filter(show == "Seinfeld")
    } else if (input$showFilter == "The Office") {
      data <- data %>% filter(show == "The Office")
    } else if (input$showFilter == "Modern Family") {
      data <- data %>% filter(show == "Modern Family")
    }
    
    return(data)
  })
  
  # Generate the ggplot
  output$sentimentPlot <- renderPlot({
    ggplot(filtered_data(), aes(x = episode, y = sentiment, color = show, group = show)) +
      geom_point(size = 3, alpha = 0.7) +
      geom_line(size = 1) +
      labs(title = paste("TextBlob Sentiment by Episode - Season", input$selectedSeason),
           x = "Episode",
           y = "Sentiment Score",
           color = "TV Show") +
      theme_minimal()
  })
  
  # Reset button action
  observeEvent(input$reset, {
    season_data <- combined_data %>% filter(season == input$selectedSeason)
    
    updateSliderInput(session, "episodeRange",
                      value = c(min(season_data$episode, na.rm = TRUE), max(season_data$episode, na.rm = TRUE)))
    
    updateRadioButtons(session, "showFilter", selected = "All")
  })
}

# Run the Shiny app
shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents