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
27: Faceting and Themes in ggplot2
I've been spending a lot of time lately cleaning up a few reports for a client, and it reminded me of a common struggle we all hit with ggplot2. You have a great dataset, you've got your x and y axes set, but the moment you add a third or fourth variable, the plot becomes a "hairball"—just a chaotic mess of overlapping points and colors that no one can actually read.
Let's look at the mpg dataset. I want to see if there's a relationship between engine displacement (displ) and highway mileage (hwy), but I suspect the trend changes depending on the type of car (class).
library(ggplot2)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
The Overplotting Problem
That's a decent start, but it's too generic. If I try to distinguish the car classes using color, it gets a bit better, but it's still crowded. I'm squinting at the screen trying to figure out where the "compact" cars end and the "subcompacts" begin.
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point()
The colors help, but the points are still on top of each other. I don't want one giant plot; I want a series of small plots, one for each car class, all using the same scale so I can compare them side-by-side. This is where faceting comes in.
Breaking it apart with facet_wrap
I'll try facet_wrap. I like this function because it's flexible—it just takes a variable and "wraps" the resulting plots into a grid that fits the page.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~class)
That's a massive improvement. Now I can clearly see that "compact" cars have a much tighter clustering than "suvs". The ~ symbol is just R's way of saying "formula," and here it tells ggplot to split the data by the class variable.
Creating a matrix with facet_grid
But what if I want to compare two categorical variables at once? Let's say I want to see class and the drive train (drv: front-wheel, rear-wheel, or 4-wheel). If I use facet_wrap, I'd just get a long list of combinations. Instead, I'll use facet_grid to create a proper matrix.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ class)
Notice the syntax: rows ~ columns. Now I have a grid where each row is a drive type and each column is a car class. It's a bit denser, but the structural comparison is immediate. I can see, for example, that 4-wheel drive cars generally have larger engines across almost all classes.
Cleaning up the aesthetic noise
Now, here is my personal gripe: the default ggplot2 grey background. It's fine for a quick check, but if I'm putting this in a presentation, it looks a bit dated and "heavy." I want something cleaner.
I'll try theme_minimal() first, which strips away the grey background and the heavy borders.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~class) +
theme_minimal()
That's much breathier. There are a few other built-in options like theme_bw() (classic white background with a thin black border) or theme_void() (which removes everything—useful for maps or diagrams), but theme_minimal() is usually my go-to for data exploration.
Going surgical with theme()
Sometimes a preset theme isn't enough. What if I like theme_minimal(), but I hate that the axis text is too small, or I want the plot title to be centered? This is where the theme() function comes in. Think of it as the "CSS of ggplot2."
I'll add a title and then use theme() to tweak the specific elements.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~class) +
labs(title = "Highway Mileage by Engine Size") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
axis.text = element_text(color = "darkblue"),
strip.background = element_rect(fill = "lightgrey")
)
A couple of things to notice here:
hjust = 0.5centers the title.element_text()is used for things made of text.element_rect()is used for things that are boxes (like the facet labels, called "strips").
📋 Practical Task
Exercise: Visualizing Diamond Quality vs. Price
Using the diamonds dataset (built into ggplot2), create a visualization that explores the relationship between carat (weight) and price.
- Create a scatter plot of
caratvsprice. - Use
facet_wrapto create a separate panel for eachcutof the diamond. - Apply
theme_bw()to the entire plot. - Use the
theme()function to:- Change the
strip.text(the facet labels) to be italicized. - Change the
plot.titleto be centered and colored "darkred".
- Change the
- Add a descriptive title to your plot using
labs().
There are no comments for now.