This lab follows Sections 1.1–1.3 of Text Mining with R: A Tidy Approach.
I explore how to organize unstructured text, separate sentences into
individual words with unnest_tokens(), remove stop words,
and visualize word frequencies.
I also explain how these techniques can support marketing decisions.
Unstructured text consists of original sentences or paragraphs, such as a customer review.
Tidy text organizes the data so that each word (or token) appears in its own row.
This format makes text easier to count, filter, and analyze in R.
Run this installation code once in the RStudio Console if needed.
install.packages(c(
"dplyr",
"tibble",
"tidytext",
"janeaustenr",
"stringr",
"ggplot2"
))
library(dplyr)
library(tibble)
library(tidytext)
library(janeaustenr)
library(stringr)
library(ggplot2)
For a small example, I use four lines from Emily Dickinson’s poem Because I could not stop for Death.
Each element contains a complete line of text.
text <- c(
"Because I could not stop for Death -",
"He kindly stopped for me -",
"The Carriage held but just Ourselves -",
"and Immortality"
)
text
## [1] "Because I could not stop for Death -"
## [2] "He kindly stopped for me -"
## [3] "The Carriage held but just Ourselves -"
## [4] "and Immortality"
text_df <- tibble(
line = seq_along(text),
text = text
)
text_df
## # A tibble: 4 × 2
## line text
## <int> <chr>
## 1 1 Because I could not stop for Death -
## 2 2 He kindly stopped for me -
## 3 3 The Carriage held but just Ourselves -
## 4 4 and Immortality
The unnest_tokens() function creates one row per
word.
By default, it converts words to lowercase and removes punctuation.
tidy_poem <- text_df %>%
unnest_tokens(word, text)
tidy_poem
## # A tibble: 20 × 2
## line word
## <int> <chr>
## 1 1 because
## 2 1 i
## 3 1 could
## 4 1 not
## 5 1 stop
## 6 1 for
## 7 1 death
## 8 2 he
## 9 2 kindly
## 10 2 stopped
## 11 2 for
## 12 2 me
## 13 3 the
## 14 3 carriage
## 15 3 held
## 16 3 but
## 17 3 just
## 18 3 ourselves
## 19 4 and
## 20 4 immortality
The output preserves each word’s original line number while converting the poem into one-word-per-row data.
This structure makes it easier to examine individual words instead of full sentences.
The janeaustenr package provides six novels written by
Jane Austen.
This larger dataset makes it possible to explore word patterns across many pages of text.
original_books <- austen_books() %>%
group_by(book) %>%
mutate(
linenumber = row_number(),
chapter = cumsum(str_detect(
text,
regex(
"^chapter\\s+([0-9]+|[ivxlcdm]+)\\b",
ignore_case = TRUE
)
))
) %>%
ungroup()
original_books
## # A tibble: 73,422 × 4
## text book linenumber chapter
## <chr> <fct> <int> <int>
## 1 "SENSE AND SENSIBILITY" Sense & Sensibility 1 0
## 2 "" Sense & Sensibility 2 0
## 3 "by Jane Austen" Sense & Sensibility 3 0
## 4 "" Sense & Sensibility 4 0
## 5 "(1811)" Sense & Sensibility 5 0
## 6 "" Sense & Sensibility 6 0
## 7 "" Sense & Sensibility 7 0
## 8 "" Sense & Sensibility 8 0
## 9 "" Sense & Sensibility 9 0
## 10 "CHAPTER 1" Sense & Sensibility 10 1
## # ℹ 73,412 more rows
tidy_books <- original_books %>%
unnest_tokens(word, text)
tidy_books
## # A tibble: 725,064 × 4
## book linenumber chapter word
## <fct> <int> <int> <chr>
## 1 Sense & Sensibility 1 0 sense
## 2 Sense & Sensibility 1 0 and
## 3 Sense & Sensibility 1 0 sensibility
## 4 Sense & Sensibility 3 0 by
## 5 Sense & Sensibility 3 0 jane
## 6 Sense & Sensibility 3 0 austen
## 7 Sense & Sensibility 5 0 1811
## 8 Sense & Sensibility 10 1 chapter
## 9 Sense & Sensibility 10 1 1
## 10 Sense & Sensibility 13 1 the
## # ℹ 725,054 more rows
Each row now contains the book name, line number, chapter, and one word.
Common words such as “the,” “and,” and “is” can overwhelm the results.
The stop_words dataset identifies these words, and
anti_join() removes them.
clean_books <- tidy_books %>%
anti_join(stop_words, by = "word")
clean_books
## # A tibble: 217,602 × 4
## book linenumber chapter word
## <fct> <int> <int> <chr>
## 1 Sense & Sensibility 1 0 sense
## 2 Sense & Sensibility 1 0 sensibility
## 3 Sense & Sensibility 3 0 jane
## 4 Sense & Sensibility 3 0 austen
## 5 Sense & Sensibility 5 0 1811
## 6 Sense & Sensibility 10 1 chapter
## 7 Sense & Sensibility 10 1 1
## 8 Sense & Sensibility 13 1 family
## 9 Sense & Sensibility 13 1 dashwood
## 10 Sense & Sensibility 13 1 settled
## # ℹ 217,592 more rows
Word frequency measures how often individual words appear in the dataset.
word_counts <- clean_books %>%
count(word, sort = TRUE)
word_counts
## # A tibble: 13,910 × 2
## word n
## <chr> <int>
## 1 miss 1855
## 2 time 1337
## 3 fanny 862
## 4 dear 822
## 5 lady 817
## 6 sir 806
## 7 day 797
## 8 emma 787
## 9 sister 727
## 10 house 699
## # ℹ 13,900 more rows
Character names and frequently used terms appear near the top of the results.
This reveals patterns in the vocabulary used throughout Jane Austen’s novels.
However, word frequency alone cannot determine the meaning or emotional tone of a sentence.
The following chart displays words that appear more than 600 times after removing stop words.
word_counts %>%
filter(n > 600) %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(x = n, y = word)) +
geom_col(
fill = "#42657B",
width = 0.75
) +
labs(
title = "Most Frequent Words in Jane Austen's Novels",
subtitle = "Word counts after removing stop words",
x = "Number of occurrences",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.major.y = element_blank()
)
Text mining provides marketers with an effective way to understand customer feedback and behavior.
Businesses can apply the same process to customer reviews, social media comments, and survey responses.
For example, frequently mentioned words such as “price,” “delivery,” or “quality” may identify topics that customers consider important.
By examining these patterns, companies can recognize recurring customer concerns and improve marketing strategies.
However, marketers should examine the original text before drawing conclusions, since word frequency does not necessarily indicate positive or negative sentiment.
This exercise demonstrated how unstructured text can be transformed
into organized data using the tidytext package in R.
Through tokenization, stop-word removal, and word frequency analysis, I learned how to identify and visualize commonly used words.
These techniques provide a foundation for further text mining and can help businesses better understand customer communication and preferences.
Silge, J., & Robinson, D. (2017). Text Mining with R: A Tidy Approach.