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