Christmas Novels

text analysis
sentiment
christmas
wordcloud
Sentiment analysis on Christmas novels
Author

Cole Baril

Published

December 30, 2025

Load Packages

require(pacman)
p_load(tidytuesdayR, magick, tidyverse, janitor, tidytext, extrafont, slider, here, TTR, wordcloud2, tm, textdata, treemapify, trashpanda)

Load Data

tuesdata <- tidytuesdayR::tt_load('2025-12-30')
christmas_novel_authors <- tuesdata$christmas_novel_authors
christmas_novel_text <- tuesdata$christmas_novel_text
christmas_novels <- tuesdata$christmas_novels

Data Cleaning

text <- christmas_novel_text |> select(2) |> 
  unnest_tokens(word, text)

word_cleaned <- text |> 
  drop_na() |> 
  anti_join(stop_words, by = "word") |> 
  filter(!word %in% stopwords("en")) |> 
  filter(!word %in% stopwords("de")) 

wordcount <- word_cleaned |> 
  count(word, sort = TRUE) 

Word Cloud

christmas_cozy <- colorRampPalette(
  c("#7A1F1F",  # muted cranberry
    "#B11226",  # warm red
    "#F4F1EC",  # warm snow
    "#1F4D2B",  # forest green
    "#E6C77A")  # soft gold
)(100)

set.seed(123)
christmas_cozy_random <- sample(christmas_cozy, size = 100)

wordcloud2(head(wordcount, 100), size = 0.8, color = christmas_cozy_random, backgroundColor = "black")

Sentiment Analysis

nrc <- get_sentiments("nrc")

plot <- word_cleaned %>% 
  inner_join(get_sentiments("nrc"), relationship = "many-to-many") %>% 
  count(word, sentiment) %>% 
  pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) %>% 
  select_if(is.numeric) %>% 
  map_dbl(sum) %>% 
  as.data.frame() %>% 
  rownames_to_column("Emotion") %>% 
  rename("number" = ".") %>% 
  mutate(across(where(is.character), tools::toTitleCase)) %>% 
  ggplot(aes(area = number, fill = Emotion, label = Emotion)) +
  geom_treemap() + 
  geom_treemap_text(colour = "Black", 
                    place = "centre",
                    size = 25) +
  scale_fill_manual(
    values = c(
      "#E07A7A",  # soft holly red
      "#F2A1A1",  # candy cane red
      "#C94C4C",  # muted cranberry
      "#7FB3A6",  # frosted pine
      "#A3C9A8",  # sage green
      "#5FA39A",  # misty evergreen
      "#F3E1A0",  # pale gold
      "#FFF1C1",  # warm snow
      "#E6E6E6",  # winter frost
      "#B0B7C3"   # icy silver
    ),
    guide = "none"
  ) +
  labs(title = "What Does a Christmas Novel Feel Like?",
       subtitle = "Joy, trust, and positivity lead the way") +
  theme_bw(base_size = 20) +
  add_caption_cwb(type = "plot", include_data_source = TRUE, data_source = "Project Gutenberg | Tidy Tuesday") +
  theme(panel.grid.major.x = element_blank(),
        panel.grid.major.y = element_blank(),
        panel.grid.minor.x = element_blank(),
        panel.grid.minor.y = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        plot.title = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5),
        legend.title = element_text(hjust = 0.5),
        legend.background = element_rect(fill = "#f5f5f2"),
        plot.background = element_rect(fill = "#f5f5f2", color = "#f5f5f2"),
        panel.background = element_rect(fill = "#f5f5f2", color = "#f5f5f2"),
        panel.border = element_blank(),
        axis.line.y = element_line(colour = "black"))

# Save and display images
current_dir <- dirname(knitr::current_input())
plot_name <- "xmas_novel_sentiments.png"

ggsave(plot = plot, 
       dpi = "screen",
       width = 14,
       height = 14,
       device = ragg::agg_png,
       filename = file.path(current_dir, plot_name))


# Read the big plot
img <- image_read(file.path(current_dir, plot_name))

# Force 16:9 aspect ratio with minimal padding
# Target size: 1200x675 px (16:9)
img_card <- image_scale(img, "1200x675")           # scale to fit inside 16:9
img_card <- image_extent(
  img_card,
  geometry = "1200x675",
  gravity = "center"
)

# Save as card preview
image_write(img_card, path = file.path(current_dir, "preview.png"))

knitr::include_graphics(
  file.path(current_dir, plot_name)
)

References

trashpanda::cite_packages(format = "rmd")
  1. Baril C (????). trashpanda: Cole’s Personal Collection of R Functions, Themes, and Palettes. R package version 0.0.1, https://colebaril.github.io/trashpanda/.

  2. Wilkins D (2025). treemapify: Draw Treemaps in ‘ggplot2’. doi:10.32614/CRAN.package.treemapify https://doi.org/10.32614/CRAN.package.treemapify, R package version 2.6.0, https://CRAN.R-project.org/package=treemapify.

  3. Hvitfeldt E (2024). textdata: Download and Load Various Text Datasets. doi:10.32614/CRAN.package.textdata https://doi.org/10.32614/CRAN.package.textdata, R package version 0.4.5, https://CRAN.R-project.org/package=textdata.

  4. Feinerer I, Hornik K (2026). tm: Text Mining Package. doi:10.32614/CRAN.package.tm https://doi.org/10.32614/CRAN.package.tm, R package version 0.7-18, https://CRAN.R-project.org/package=tm.

Feinerer I, Hornik K, Meyer D (2008). “Text Mining Infrastructure in R.” Journal of Statistical Software, 25(5), 1-54. doi:10.18637/jss.v025.i05 https://doi.org/10.18637/jss.v025.i05.

  1. Hornik K (2024). NLP: Natural Language Processing Infrastructure. doi:10.32614/CRAN.package.NLP https://doi.org/10.32614/CRAN.package.NLP, R package version 0.3-2, https://CRAN.R-project.org/package=NLP.

  2. Lang D, Chien G (2018). wordcloud2: Create Word Cloud by ‘htmlwidget’. doi:10.32614/CRAN.package.wordcloud2 https://doi.org/10.32614/CRAN.package.wordcloud2, R package version 0.2.1, https://CRAN.R-project.org/package=wordcloud2.

  3. Ulrich J (2023). TTR: Technical Trading Rules. doi:10.32614/CRAN.package.TTR https://doi.org/10.32614/CRAN.package.TTR, R package version 0.24.4, https://CRAN.R-project.org/package=TTR.

  4. Müller K (2025). here: A Simpler Way to Find Your Files. doi:10.32614/CRAN.package.here https://doi.org/10.32614/CRAN.package.here, R package version 1.0.2, https://CRAN.R-project.org/package=here.

  5. Vaughan D (2025). slider: Sliding Window Functions. doi:10.32614/CRAN.package.slider https://doi.org/10.32614/CRAN.package.slider, R package version 0.3.3, https://CRAN.R-project.org/package=slider.

  6. Chang W (2025). extrafont: Tools for Using Fonts. doi:10.32614/CRAN.package.extrafont https://doi.org/10.32614/CRAN.package.extrafont, R package version 0.20, https://CRAN.R-project.org/package=extrafont.

  7. Silge J, Robinson D (2016). “tidytext: Text Mining and Analysis Using Tidy Data Principles in R.” JOSS, 1(3). doi:10.21105/joss.00037 https://doi.org/10.21105/joss.00037, http://dx.doi.org/10.21105/joss.00037.

  8. Firke S (2024). janitor: Simple Tools for Examining and Cleaning Dirty Data. doi:10.32614/CRAN.package.janitor https://doi.org/10.32614/CRAN.package.janitor, R package version 2.2.1, https://CRAN.R-project.org/package=janitor.

  9. Grolemund G, Wickham H (2011). “Dates and Times Made Easy with lubridate.” Journal of Statistical Software, 40(3), 1-25. https://www.jstatsoft.org/v40/i03/.

  10. Wickham H (2025). forcats: Tools for Working with Categorical Variables (Factors). doi:10.32614/CRAN.package.forcats https://doi.org/10.32614/CRAN.package.forcats, R package version 1.0.1, https://CRAN.R-project.org/package=forcats.

  11. Wickham H (2025). stringr: Simple, Consistent Wrappers for Common String Operations. doi:10.32614/CRAN.package.stringr https://doi.org/10.32614/CRAN.package.stringr, R package version 1.6.0, https://CRAN.R-project.org/package=stringr.

  12. Wickham H, François R, Henry L, Müller K, Vaughan D (2023). dplyr: A Grammar of Data Manipulation. doi:10.32614/CRAN.package.dplyr https://doi.org/10.32614/CRAN.package.dplyr, R package version 1.1.4, https://CRAN.R-project.org/package=dplyr.

  13. Wickham H, Henry L (2026). purrr: Functional Programming Tools. doi:10.32614/CRAN.package.purrr https://doi.org/10.32614/CRAN.package.purrr, R package version 1.2.1, https://CRAN.R-project.org/package=purrr.

  14. Wickham H, Hester J, Bryan J (2025). readr: Read Rectangular Text Data. doi:10.32614/CRAN.package.readr https://doi.org/10.32614/CRAN.package.readr, R package version 2.1.6, https://CRAN.R-project.org/package=readr.

  15. Wickham H, Vaughan D, Girlich M (2025). tidyr: Tidy Messy Data. doi:10.32614/CRAN.package.tidyr https://doi.org/10.32614/CRAN.package.tidyr, R package version 1.3.2, https://CRAN.R-project.org/package=tidyr.

  16. Müller K, Wickham H (2026). tibble: Simple Data Frames. doi:10.32614/CRAN.package.tibble https://doi.org/10.32614/CRAN.package.tibble, R package version 3.3.1, https://CRAN.R-project.org/package=tibble.

  17. Wickham H (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. ISBN 978-3-319-24277-4, https://ggplot2.tidyverse.org.

  18. Wickham H, Averick M, Bryan J, Chang W, McGowan LD, François R, Grolemund G, Hayes A, Henry L, Hester J, Kuhn M, Pedersen TL, Miller E, Bache SM, Müller K, Ooms J, Robinson D, Seidel DP, Spinu V, Takahashi K, Vaughan D, Wilke C, Woo K, Yutani H (2019). “Welcome to the tidyverse.” Journal of Open Source Software, 4(43), 1686. doi:10.21105/joss.01686 https://doi.org/10.21105/joss.01686.

  19. Ooms J (2025). magick: Advanced Graphics and Image-Processing in R. doi:10.32614/CRAN.package.magick https://doi.org/10.32614/CRAN.package.magick, R package version 2.9.0, https://CRAN.R-project.org/package=magick.

  20. Harmon J, Hughes E (2025). tidytuesdayR: Access the Weekly ‘TidyTuesday’ Project Dataset. doi:10.32614/CRAN.package.tidytuesdayR https://doi.org/10.32614/CRAN.package.tidytuesdayR, R package version 1.2.1, https://CRAN.R-project.org/package=tidytuesdayR.

  21. Rinker TW, Kurkiewicz D (2018). pacman: Package Management for R. version 0.5.0, http://github.com/trinker/pacman.