Skip to main content
Free webinar: Build AI agents in R you can trust, 19 Nov, 1:15pm UK Register

See all results
items
    • Overview 
    • Join Us  
    • Community 
    • Contact 
    • Overview 
    • Course Catalogue 
    • Public Courses 
    • Overview 
    • AI New 
    • Posit 
    • Data Science 
    • Engineering 
    • Blog 
    • Case Studies 
    • R Package Validation 
    • Gallery 
    • diffify  
    • Pro Bono Support 

Edinbr: Text Mining with R

Published: February 24, 2018

tags: rtidyverse, tidytext, edinbr

During a very quick tour of Edinburgh (and in particular some distilleries), Dave Robinson (Tidytext fame), was able to drop by the Edinburgh R meet-up group to give a very neat talk on tidy text. The first part of the talk set the scene

  • What does does text mean?
  • Why make text tidy?
  • What sort of problems can you solve?

This was a very neat overview of the topic and gave persuasive arguments around the idea of using a data frame for manipulating text. Most of the details are in Julie’s and his book on Text Mining with R.

Do you use Professional Posit Products? If so, check out our managed Posit services.

Personally, I found the second part of his talk the most interesting, where Dave did an “off the cuff” demonstration of a tidy text analysis of the “Scottish play” (see Blackadder for details on the “Scottish play”).

After loading a few packages

library("gutenbergr")
library("tidyverse")
library("tidytext")
library("zoo")

He downloaded the “Scottish Play” via the Gutenbergr package

macbeth = gutenberg_works(title == "Macbeth") %>%
  gutenberg_download()

Then proceeded to generate a bar chart of the top \(10\) words (excluding stop words such as and, to), via

macbeth %>%
  unnest_tokens(word, text) %>% # Make text tidy
  count(word, sort = TRUE) %>% # Count occurances
  anti_join(stop_words, by = "word") %>% # Remove stop words
  head(10) %>% # Select top 10
  ggplot(aes(word, n)) + # Plot
  geom_col()

The two key parts of this code are

  • unnest_tokens() - used to tidy the text;
  • anti_join() - remove any stop_words.

Since this analysis was “off the cuff”, Dave noticed that we could easily extract the speaker. This is clearly something you would want to store and can be achieved via a some mutate() magic

speaker_words = macbeth %>%
  mutate(is_speaker = str_detect(text, "^[A-Z ]+\\.$"), # Detect capital letters
         speaker = ifelse(is_speaker, text, NA),
         speaker = na.locf(speaker, na.rm = FALSE))

The str_detect() uses a simple regular expression to determine if the text are capital letters (theyby indicating a scene). Any expression of length zero is replaced, by a missing value NA. Before finishing with the {zoo} na.locf() function to carry the last observation forward, thereby filling the blanks.

The resulting tibble is then cleaned using

speaker_words = speaker_words %>%
  filter(!is_speaker, !is.na(speaker)) %>%
  select(-is_speaker, -gutenberg_id) %>%
  unnest_tokens(word, text) %>%
  anti_join(stop_words, by = "word")

A further bit of analysis gives

speaker_words %>%
  count(speaker, word, sort = TRUE) %>%
  bind_tf_idf(word, speaker, n) %>%
  arrange(desc(tf_idf)) %>%
  filter(n >= 5)
## # A tibble: 107 x 6
##    speaker       word         n      tf   idf tf_idf
##    <chr>         <chr>    <int>   <dbl> <dbl>  <dbl>
##  1 PORTER.       knock       10 0.0847  3.09  0.262
##  2 ALL.          double       6 0.0588  2.40  0.141
##  3 PORTER.       knocking     6 0.0508  2.40  0.122
##  4 APPARITION.   macbeth      5 0.143   0.788 0.113
##  5 LADY MACDUFF. thou         5 0.0394  1.30  0.0512
##  6 PORTER.       sir          5 0.0424  1.15  0.0485
##  7 DUNCAN.       thee         6 0.0270  1.30  0.0351
##  8 FIRST WITCH.  macbeth      7 0.0417  0.788 0.0329
##  9 LADY MACBETH. wouldst      6 0.00825 3.78  0.0312
## 10 MACDUFF.      scotland     8 0.0154  1.99  0.0306
## # ... with 97 more rows

In my opinion, the best part of the night was the lively question and answer session. The questions were on numerous topics (I didn’t write them down sorry!), that Dave handled with ease, usually with another off-the-cuff demo.

Further Links

  • Edinburgh R user group
  • Text mining with R: amazon
  • Dave Robinson: twitter, blog
  • Blackadder discusses the Scottish play

Jumping Rivers Logo

You might also like

Why R, and where the budget goes

Planning a move from SAS to R? Find out why R stands up to regulators, where the cost and risk of a migration come from, and the four things to settle before you convert a line of code.

Agents in Production: From Chatbot to Agent

We asked Gemini how many people on the high dose of a drug had itching in a well-known clinical trial. It said 21, and sounded sure of it. We asked again and got 25, with different numbers for the other groups too. Both answers cited the trial's data files, but the model hadn't been given them.

PHUSE EU Connect 2026

Jumping Rivers is exhibiting at PHUSE EU Connect 2026 in Glasgow, 15–18 November. Here's who you'll meet and what we'll be talking about.

You Might Also Like

  • SAS to R: Why R, and Where Your Migration Budget Should Go
  • Agents in Production: Build Your First AI Agent in R with {ellmer}
  • We're heading to PHUSE EU Connect 2026

Recent Posts

  • SAS to R: Why R, and Where Your Migration Budget Should Go 
  • Agents in Production: Build Your First AI Agent in R with {ellmer} 
  • We're heading to PHUSE EU Connect 2026 
  • Agents in Production Webinar: From a Chatbot to a Tool You Can Rely On 
  • Spring 2027 data science training courses: January to June 
  • What is an MCP server? 
  • AI in Production 2027 Call for Speakers: What Makes a Strong Talk 
  • What's New in Python 3.15? 
  • Autumn 2026 Data Science Training Courses 
  • Using GitHub Actions to deploy to Posit Connect Cloud 

Keep Updated

Like data science? R? Python? Stan? Then you’ll love the Jumping Rivers newsletter. The perks of being part of the Jumping Rivers family are:

  • Be the first to know about our latest courses and conferences.
  • Get discounts on the latest courses.
  • Read news on the latest techniques with the Jumping Rivers blog.

We keep your data secure and will never share your details. By subscribing, you agree to our privacy policy.

Follow Us

  • GitHub
  • Bluesky
  • LinkedIn
  • YouTube
  • Eventbrite

Find Us

The Catalyst Newcastle Helix Newcastle, NE4 5TG
Get directions

Contact Us

  • hello@jumpingrivers.com
  • + 44(0) 191 432 4340

Newsletter

Sign up

Events

  • North East Data Scientists Meetup
  • Leeds Data Science Meetup
  • AI in Production
  • Webinars
British Assessment Bureau, UKAS Certified logo for ISO 9001 - Quality management British Assessment Bureau, UKAS Certified logo for ISO 27001 - Information security management Cyber Essentials Certified Plus badge Accredited Living Wage Employer
  • Privacy Notice
  • |
  • Booking Terms

©2016 - present. Jumping Rivers Ltd