A timeline of Sentiments in plays of William Shakespeare
Sentinment Analysis reveals how sentiments move from positve to negative in latter half of the 3 popular plays by William Shakespeare
#TidyTuesday
{tidytext}
Author
Aditya Dahiya
Published
September 17, 2024
This week’s #TidyTuesday dataset explores the rich dialogue found in the works of William Shakespeare, specifically focusing on Hamlet, Macbeth, and Romeo and Juliet. The dataset, sourced from shakespeare.mit.edu and curated by Nicola Rennie, offers insights into the structure and dynamics of Shakespeare’s plays. The accompanying graphic illustrates the flow of sentiments (using sentiment analysis (Silge and Robinson 2016)) from positive to negative over the course of each play, revealing that while both Hamlet and Romeo and Juliet end on a somber note, Macbeth concludes with a surprising uplift despite its tragic themes.
How I made this graphic?
Loading libraries & data
Code
# Data Import and Wrangling Toolslibrary(tidyverse) # All things tidy# Final plot toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text support for ggplot2library(showtext) # Display fonts in ggplot2library(colorspace) # Lighten and Darken colourslibrary(patchwork) # Combining plotslibrary(tidytext) # Text & Sentiment Analysis# Option 1: tidytuesdayR package tuesdata <- tidytuesdayR::tt_load(2024, week =38)hamlet <- tuesdata$hamletmacbeth <- tuesdata$macbethromeo_juliet <- tuesdata$romeo_julietrm(tuesdata)
Data Wrangling and EDA
Code
# A custom function to convert Roman numerals to numbersroman_to_num_map <-c(I =1, II =2, III =3, IV =4, V =5, VI =6, VII =7, VIII =8, IX =9, X =10)roman_to_number <-function(roman_vector) { roman_vector %>%map_dbl(~ roman_to_num_map[.x])}# Function to convert numbers to Roman numerals# Reverse the mapping to create a number-to-Roman mapnum_to_roman_map <-set_names(names(roman_to_num_map), roman_to_num_map)number_to_roman <-function(num_vector) { num_vector %>%map_chr(~ num_to_roman_map[as.character(.x)])}# Custom function to calculate the modeget_mode <-function(temp) { temp |>as_tibble() |>count(value) |>slice_max(order_by = n, n =1) |>pull(value)}# Sentiments under afinnsentiment_df <-get_sentiments("afinn")# A function to generate the sentiments timeline for any bookget_sentiment_graph_data <-function(dataset){ dataset |>mutate(act =str_remove(act, "Act "),scene =str_remove(scene, "Scene "),act =roman_to_number(act),scene =roman_to_number(scene) ) |>select(-character) |>unnest_tokens(output ="word",input = dialogue ) |>inner_join(sentiment_df) |>mutate(id =row_number(),id =round(rescale(id), 2) ) |>group_by(id) |>summarise(sent_value =sum(value, na.rm = T),act =get_mode(act) )}# Composing the final dataframe for the plotplotdf <-bind_rows(get_sentiment_graph_data(macbeth) |>mutate(novel ="Macbeth"),get_sentiment_graph_data(romeo_juliet) |>mutate(novel ="Romeo and Juliet"),get_sentiment_graph_data(hamlet) |>mutate(novel ="Hamlet"))plotdf_acts <- plotdf |>group_by(novel, act) |>summarise(xmin =min(id),xmax =max(id),xmed = (xmin + xmax)/2 ) |>mutate(act =number_to_roman(act))
Visualization Parameters
Code
# Font for titlesfont_add_google("Maiden Orange",family ="title_font") # Font for the captionfont_add_google("Stint Ultra Condensed",family ="caption_font") # Font for plot textfont_add_google("BioRhyme",family ="body_font") showtext_auto()mypal <-c("#DF6589FF", "#603F83FF", "#C7D3D4FF", "#3C1053FF")bg_col <- mypal[3]text_col <- mypal[4]text_hil <- mypal[4]bts <-90# Caption stuff for the plotsysfonts::font_add(family ="Font Awesome 6 Brands",regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf"))github <-""github_username <-"aditya-dahiya"xtwitter <-""xtwitter_username <-"@adityadahiyaias"social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_hil}'>{github_username} </span>")social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil}'>{xtwitter_username}</span>")plot_title <-"Sentiments in Shakespeare’s Plays"plot_subtitle <-"The flow of sentiments (positive to negative) across three Shakespearean plays, over the progression of the narrative (0% to 100%). While Hamlet, and, Romeo and Juliet culminate in sorrow, Macbeth transitions from sadness to a positive conclusion."plot_caption <-paste0("**Data:** shakespeare.mit.edu & Nicola Rennie", " | **Code:** ", social_caption_1, " | **Graphics:** ", social_caption_2 )rm(github, github_username, xtwitter, xtwitter_username, social_caption_1, social_caption_2)