-
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
157: Practice Exercise: Building a Multi-Panel Dashboard Report
How do I actually arrange different plots into a grid without it becoming a mess?
If you've tried using par(mfrow = ...) or grid.arrange(), you know it can feel clunky. I almost always use the patchwork package now. It treats ggplot objects like mathematical expressions, which is honestly a game-changer for building dashboards. You can use + to put plots side-by-side and / to stack them on top of each other.
library(ggplot2)
library(patchwork)
# Let's imagine we're tracking e-commerce sales
p1 <- ggplot(sales_data, aes(x = date, y = revenue)) +
geom_line(color = "steelblue") +
labs(title = "Daily Revenue")
p2 <- ggplot(sales_data, aes(x = category, y = revenue)) +
geom_col(fill = "darkseagreen") +
labs(title = "Revenue by Category")
p3 <- ggplot(sales_data, aes(x = region, y = orders)) +
geom_bar(fill = "indianred") +
labs(title = "Orders by Region")
# This is where the magic happens:
# p1 on top, p2 and p3 side-by-side underneath
dashboard <- p1 / (p2 + p3)
dashboard
How do I handle titles and labels so they don't look redundant?
One thing that makes a dashboard look "amateur" is repeating the same axis labels on every single panel. If every plot says "Revenue (USD)" on the Y-axis, it's just visual noise. I usually strip the axis titles from the individual plots and instead use plot_annotation() to give the entire dashboard one clear, overarching title and subtitle.
Here is how I'd clean that up:
# Remove axis labels from the individual plots
p1 <- p1 + labs(x = NULL, y = NULL)
p2 <- p2 + labs(x = NULL, y = NULL)
p3 <- p3 + labs(x = NULL, y = NULL)
# Add the global dashboard heading
dashboard <- (p1 / (p2 + p3)) +
plot_annotation(
title = 'Q3 Executive Sales Performance',
subtitle = 'Analysis of regional growth and product category trends',
caption = 'Data sourced from Internal Warehouse API'
)
What's the best way to make the panels feel like a cohesive report?
The secret is consistency in theme and layout ratios. If one plot is a tiny square and the other is a giant rectangle, the eye doesn't know where to land. You can use plot_layout() to specify exactly how much space each plot should take. I also highly recommend defining a single theme object and applying it to all plots—this ensures your fonts, grid lines, and margins are identical across the board.
Try this approach to balance the visual weight:
# Define a consistent look
my_theme <- theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))
# Apply theme and set the top plot to take up 60% of the height
dashboard <- (p1 + my_theme) / (p2 + my_theme + p3 + my_theme) +
plot_layout(heights = c(2, 1))
dashboard
📋 Practical Task
Exercise: Build a Regional Healthcare Utilization Dashboard
You have been provided with a dataset health_stats containing three columns: clinic_id, patient_count, wait_time, and region. Your goal is to create a professional multi-panel report using patchwork.
Requirements:
- Plot A: A boxplot of
wait_timegrouped byregion. - Plot B: A bar chart showing the total
patient_countperregion. - Plot C: A scatter plot of
patient_countvswait_time. - Layout: Arrange the plots so that the scatter plot (Plot C) occupies the top row (full width), and the boxplot and bar chart (Plots A and B) are side-by-side on the bottom row.
- Styling: Remove all individual X and Y axis titles. Add a global title "Regional Healthcare Efficiency Report" and a subtitle "Analyzing patient throughput and wait times across districts" using
plot_annotation(). - Balance: Use
plot_layout()to ensure the top plot is twice as tall as the bottom row.
There are no comments for now.