R
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
108: Topic Modeling with Latent Dirichlet Allocation
You've probably spent the last few lessons cleaning your text data—removing stop words, stemming, and getting everything into a nice, tidy tibble. Now you want to find the "hidden" themes in your documents using Latent Dirichlet Allocation (LDA). But when you try to run your first model, you're likely to hit a wall like this:
library(topicmodels)
library(tidytext)
# Assume 'reviews_tidy' is a tidy tibble with 'document' and 'term' columns
lda_model <- LDA(reviews_tidy, k = 5, control = list(seed = 123))
# Error in .local(x, k, ...) : x must be a DocumentTermMatrix
The Matrix Mismatch
This is the most common stumbling block I see. You're using the tidytext ecosystem, which loves "long" data (one word per row). However, the topicmodels package is older and expects a DocumentTermMatrix (DTM). A DTM is essentially a giant spreadsheet where every row is a document and every column is a unique word in your entire vocabulary. The LDA() function cannot read a tibble; it needs that specific matrix object.
To fix this, we use cast_dtm(). This function takes your tidy data and "pivots" it into the format the LDA algorithm requires. Here is the corrected flow:
# Convert the tidy tibble into a DocumentTermMatrix
dtm <- reviews_tidy %>%
cast_dtm(term = term, document = document)
# Now pass the DTM into the LDA function
lda_model <- LDA(dtm, k = 5, control = list(seed = 123))
By casting the data first, you've transformed your list of words into a mathematical representation that the model can actually compute. I usually recommend checking the dimensions of your DTM with dim(dtm) before running the model—if you have 50,000 unique words, your model might crawl to a halt.
Interpreting the Probabilities
Once the model runs, you'll realize LDA doesn't just "tell" you what the topics are. It doesn't name them "Customer Service" or "Pricing." Instead, it gives you two sets of probabilities: $\beta$ (beta) and $\gamma$ (gamma). I like to think of these as the "What" and the "Where."
- $\beta$ (Topic-Word probabilities): This tells you which words are most associated with which topic. For example, if Topic 1 has high probabilities for "battery," "charge," and "power," you can manually label that topic as "Battery Life."
- $\gamma$ (Document-Topic probabilities): This tells you how much of each document is composed of each topic. A single review might be 70% "Battery Life" and 30% "Shipping Speed."
To get these into a usable format, use the tidy() function from tidytext. It turns those complex model objects back into the tidy tibbles we actually enjoy working with.
# Get the word-topic probabilities (beta)
topics <- tidy(lda_model, matrix = "beta")
# Get the document-topic probabilities (gamma)
doc_topics <- tidy(lda_model, matrix = "gamma")
The Art of Choosing k
The biggest headache in LDA is picking k, the number of topics. If k is too small, your topics will be overly broad (e.g., everything is just "General Feedback"). If k is too large, you'll get redundant topics that are nearly identical.
There isn't a magic button for this, but I usually follow a "bracket" approach. I'll run the model with 3, 5, 10, and 20 topics. I then look at the top 10 words for each topic. When the topics start feeling too fragmented or the same words keep appearing in every single topic, I know I've pushed k too far. It's an iterative process—more of an art than a hard science.
📋 Practical Task
Uncovering Themes in App Store Reviews
You have been given a dataset of 500 user reviews for a fictional fitness app. Your goal is to identify the top 3 themes users are discussing without reading every single review.
Your Task:
- Create a small sample tidy tibble (or use a provided one) with columns
documentandterm. - Convert this tidy data into a
DocumentTermMatrixusingcast_dtm(). - Fit an LDA model with
k = 3. - Use the
tidy()function to extract the $\beta$ matrix. - For each of the 3 topics, identify the top 5 words with the highest probability.
- Based on those words, assign a human-readable label to each topic (e.g., "Bug Reports," "Feature Requests," "User Praise").
There are no comments for now.