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
155: Practice Exercise: Building a Custom ggplot2 Theme
Wait, do I have to call the theme function inside every single plot?
Short answer: No. If you find yourself copying and pasting ten lines of theme() code into every plot in your script, you're doing it the hard way. The "engineer's approach" here is to wrap your preferences into a custom function. This makes your code cleaner and, more importantly, if your boss decides the axis text should be navy blue instead of grey, you only have to change it in one place.
# Here is how I usually structure a custom theme function
theme_corporate <- function() {
theme_minimal() +
theme(
text = element_text(family = "serif", color = "#333333"),
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
panel.grid.minor = element_blank(),
axis.line = element_line(color = "black")
)
}
# Now you just add it like any other ggplot component
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
theme_corporate()
By returning a theme() object, your custom function behaves exactly like the built-in themes you're already using.
Why can't I just pass a color string directly to the theme?
This is a common point of frustration. You'll try to do something like axis.text = "blue" and R will throw an error. It's because ggplot2 needs to know what it's styling. Is it a piece of text? A rectangle? A line?
That's why we use "element" functions. If you're touching text, use element_text(). If you're touching a background or a border, use element_rect(). If you're touching a line, use element_line(). I like to think of these as "style containers" that hold the actual properties like color, size, or line type.
# Wrong: axis.title = "red"
# Right:
theme(axis.title = element_text(color = "red", size = 12))
# Wrong: panel.background = "white"
# Right:
theme(panel.background = element_rect(fill = "white", color = "grey80"))
Can I just "tweak" an existing theme instead of defining everything from scratch?
Absolutely. In fact, I almost always do this. Defining every single element of a plot—from the legend key spacing to the plot margin—is a nightmare and a waste of your time. The trick is to call a base theme (like theme_minimal() or theme_bw()) inside your custom function before you add your own theme() overrides.
Because ggplot2 processes these layers sequentially, your custom theme() call will overwrite only the specific elements you mention, leaving the rest of the base theme's sensible defaults intact. It's essentially "inheritance" for your plot styles.
theme_my_style <- function() {
# Start with a clean slate
theme_bw() +
# Overwrite only the things I actually care about
theme(
panel.grid.major = element_line(color = "lightgrey", linetype = "dotted"),
legend.position = "bottom"
)
}
📋 Practical Task
Exercise: Create a High-Contrast 'Dark Mode' Executive Dashboard Theme
In this exercise, you will build a professional "Dark Mode" theme intended for a high-contrast executive dashboard. Your goal is to create a function called theme_exec_dark() that makes the plot look sleek and modern.
Requirements:
- Base the theme on
theme_minimal(). - Set the overall plot background and panel background to a very dark grey (e.g.,
"#222222"). Hint: You'll need to useplot.backgroundandpanel.background. - Change all text elements to white or an off-white color so they are legible.
- Remove all gridlines entirely using
element_blank(). - Make the plot title centered, bold, and size 16.
Testing your theme: Apply your function to a plot of the iris dataset (plotting Sepal.Length vs Sepal.Width) to ensure the colors contrast correctly and the gridlines are gone.
There are no comments for now.