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
51: forcats for Factor Manipulation
If you've spent any time plotting data in R, you've likely hit the "alphabetical wall." You create a beautiful bar chart of customer satisfaction levels—"Low", "Medium", "High"—and R helpfully decides to display them as "High", "Low", "Medium" because that's how the alphabet works. It's frustrating, and for a long time, the solution felt like a chore.
The Alphabetical Nightmare
The naive way to handle this is to let R treat your categories as characters and then try to force the order at the last second. You might try to manually rename the levels using base R, like this:
# The tedious way
data$satisfaction <- factor(data$satisfaction,
levels = c("Low", "Medium", "High"))
This works fine for three categories. But imagine you're dealing with a survey with fifteen different priority levels or a list of twenty different product regions. Writing out a character vector of fifteen strings in the exact order you want is not just boring; it's a liability. One typo in a string, and R will silently turn that level into an NA. I've spent way too many hours debugging a "missing data" problem that was actually just a lowercase "l" where an uppercase "L" should have been in a levels() call.
The Fragility of Manual Leveling
Another common approach I see is trying to use match() or creating a separate lookup table to map names to integers. While this is more "programmatic," it adds a layer of complexity to your script that your future self—or your teammates—will hate. You end up with a mapping variable floating around your environment, and if the raw data changes (say, "Medium" becomes "Average"), your mapping breaks and your plots shift without warning.
This is where forcats comes in. It treats factors as first-class citizens. Instead of you telling R exactly what the levels are, you tell R how the levels should behave.
Ordering by Value, Not by Name
In the real world, we rarely want things alphabetical; we usually want them ordered by some other metric. If you want to order your categories by the mean of another variable—say, ordering "Regions" by their "Total Sales"—don't manually sort the sales, find the names, and pass them to factor(). Use fct_reorder().
library(forcats)
# Order regions by the value of sales
data <- data %>%
mutate(region = fct_reorder(region, sales))
I love this because it's dynamic. If next month's data shows that the "North" region jumped from last to first, your code doesn't change, and your plot updates automatically. You've decoupled the ordering logic from the data values themselves.
Cleaning Up the Long Tail
Finally, there's the problem of the "Long Tail." You might have a column for "City," and while you have 500 cities, 90% of your revenue comes from the top five. A bar chart with 500 bars is useless. The naive approach is to write a massive case_when()` statement to manually group the small cities into an "Other" category.
That's a waste of your time. fct_lump() does this in one line. It looks at the frequency of the levels and collapses everything below a certain threshold into a single category.
# Keep the top 5 cities, lump everything else into "Other"
data <- data %>%
mutate(city = fct_lump(city, n = 5))
By using forcats, you stop treating factors as a weird R quirk you have to manage with manual lists and start treating them as a data type you can manipulate with intent. It turns a tedious manual process into a reproducible pipeline.
📋 Practical Task
Exercise: Organizing Product Category Performance
You have a dataset of product sales across various categories. Some categories are very rare, and the current alphabetical ordering makes the performance report hard to read.
Your Goal: Use the forcats package to clean up the category factor in the provided data frame. You must:
- Collapse all categories that appear fewer than 3 times into a single category called "Other".
- Reorder the remaining categories so they are sorted by the
average_spendin descending order (highest spend first).
# Initial Data
library(tidyverse)
library(forcats)
product_data <- data.frame(
category = c("Electronics", "Electronics", "Electronics", "Clothing", "Clothing",
"Home", "Home", "Books", "Books", "Beauty", "Toys", "Garden", "Sports"),
average_spend = c(120, 150, 130, 40, 50, 80, 90, 20, 25, 60, 30, 45, 70)
)
# Your code here:
# 1. Lump the categories
# 2. Reorder the categories by average_spend
There are no comments for now.