R: R ggplot2 Advanced
Last updated: 2026-08-26
In the previous lesson, we learned the ggplot2 "three-part series":
ggplot() + aes() + geom_xxx(), which allows us to create five basic types of plots. In this lesson, we’ll move on to Advanced ggplot2—mastering "layer stacking" and the "faceting system" to create plots of any complexity. This is where ggplot2 truly shines.
After completing this lesson, you’ll be able to create: multi-layer composite plots, automatic face segmentation, statistical overlay, coordinate transformations, and annotations—90% of what ggplot2 can do is covered in this lesson.
1. What You'll Learn
- A Review of ggplot2's 7-layer Syntax
- Layer Overlay (Multiple Geoms + Stats)
- facet_wrap() / facet_grid() Faceting
- stat_summary() Statistics Layer
- Coordinate transforms (coord_flip / coord_polar / coord_fixed)
- annotation
- Practical Applications of Complex Combination Graphs
2. A Story of Multidimensional Analysis
(1) Challenge: How do you create visuals for 4 cities, 4 quarters, and 4 products?
Bob wants to present sales data for 4 cities × 4 quarters × 4 products—can a single chart accommodate this 3-dimensional information?
(2) The ggplot2 Solution
# Use facet_wrap() to split "Products" into 4 small plots
ggplot(sales, aes(x = quarter, y = sales, color = city, group = city)) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
facet_wrap(~ product) + # By Product Category
labs(title = "4 City × 4 Products Sales Trends")
# A Single Painting 4 Post a picture,Automatic Page Break!
1 line facet_wrap() turns 1 image into 4. That’s the power of cropping.
3. Review of ggplot2's 7-layer syntax
(1) 7-layer structure
graph TB
A[ggplot Plot] --> B[1. Data layer<br/>ggplot data]
A --> C[2. Aesthetic Mapping layer<br/>aes]
A --> D[3. Geometric Objects layer<br/>geom_xxx]
A --> E[4. Statistical Transformations layer<br/>stat_xxx]
A --> F[5. Coordinate System layer<br/>coord_xxx]
A --> G[6. Sub-section layer<br/>facet_xxx]
A --> H[7. Topic layer<br/>theme_xxx]
style A fill:#fff3cd
style B fill:#cce5ff
style C fill:#d4edda
style D fill:#f8d7da
style E fill:#e1d4ff
style F fill:#ffe1e1
style G fill:#e1ffe1
style H fill:#ffe1d4
(2) Example of Layer Overlays
ggplot(df, aes(x, y)) + # Data + Aesthetics
geom_point() + # Geometric Layer 1:Scatter points
geom_smooth() + # Geometric Layer 2:Trendline
stat_summary() + # Statistical Layer
scale_y_log10() + # Coordinate Transformation
facet_wrap(~ group) + # Sub-section
theme_minimal() # Topic
+ and stack them in bottom-to-top order.
4. facet_wrap() / facet_grid() Faceting
(1) What is a facet?
Facet = breaking down data into multiple subplots based on a specific variable:
# Cone of Inadmissibility:1 Post a picture
ggplot(sales, aes(x, y)) + geom_point()
# After splitting:4 Zhang Xiaotu
ggplot(sales, aes(x, y)) + geom_point() + facet_wrap(~ category)
(2) facet_wrap() One-Dimensional Faceting
# Split by city(4 subplots)
ggplot(sales_long, aes(x = quarter, y = sales, color = city, group = city)) +
geom_line() +
facet_wrap(~ city) +
labs(title = "Quarterly Sales by City")
# Control the Layout of Sub-Faces:nrow / ncol
facet_wrap(~ city, nrow = 2) # 2 row
facet_wrap(~ city, ncol = 4) # 4 col
(3) facet_grid() Two-Dimensional Faceting
# Split by city(row) and product(col) Two-Dimensional Section
facet_grid(rows = vars(city), cols = vars(product))
# Abbreviation
facet_grid(city ~ product)
# Formula Syntax(Old Version)
facet_grid(. ~ category) # Press only category Split Plane
facet_grid(category ~ .) # Press only category Row-Column Plane
(4) Comparison by Aspect
| Syntax | Usage |
|---|---|
facet_wrap(~ var) |
One-Dimensional Faceting (Automatic Line Breaks) |
facet_grid(var ~ .) |
One-dimensional (row) |
facet_grid(. ~ var) |
One-dimensional (column) |
facet_grid(row ~ col) |
Two-dimensional (rows × columns) |
(5) Facet Expansion
# Free Zoom(Independent coordinates for each subgraph)
facet_wrap(~ city, scales = "free") # Freedom x/y
facet_wrap(~ city, scales = "free_x") # Freedom Alone x
facet_wrap(~ city, scales = "free_y") # Freedom Alone y
# Add a tag
facet_wrap(~ city, labeller = label_both) # Display"city: Beijing"
# Control the number of subgraphs per row
facet_wrap(~ city, nrow = 2)
5. stat_summary() Statistics Layer
(1) Automatic Statistics
# Automatically Add Mean Points + Error bar
ggplot(df, aes(x = group, y = value)) +
geom_boxplot() +
stat_summary(fun = mean, geom = "point", color = "red", size = 3)
(2) Common stat Functions
| Function | Purpose |
|---|---|
mean |
Mean |
median |
Median |
sd |
Standard Deviation |
sum |
Sum |
function(x) mean(x) + sd(x) |
Custom |
(3) Practical Application: Mean + Error Bars
ggplot(df, aes(x = group, y = value, color = group)) +
geom_point(alpha = 0.3) + # Raw Data
stat_summary(fun = mean, geom = "point", size = 4, color = "red") +
stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2)
6. geom_smooth() Trendline
(1) Basic Usage
# Auto-add LOESS Trendline
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
geom_smooth()
# Linear Regression
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
geom_smooth(method = "lm")
# Close Confidence Interval
geom_smooth(method = "lm", se = FALSE)
(2) Practical Application
# Multiple lines by component
ggplot(sales_long, aes(x = quarter, y = sales, color = city, group = city)) +
geom_point() +
geom_line() +
geom_smooth(method = "lm", se = FALSE, linewidth = 0.5)
7. Coordinate Transformation
(1) coord_flip() Flip
# Horizontal Bar Chart
ggplot(df, aes(x = city, y = sales)) +
geom_col() +
coord_flip() # x/y Swap
(2) coord_polar() Polar Coordinates
# Pie Chart
ggplot(df, aes(x = 1, y = sales, fill = city)) +
geom_col() +
coord_polar(theta = "y")
# Rose Illustration
ggplot(df, aes(x = city, y = sales, fill = city)) +
geom_col() +
coord_polar()
(3) coord_fixed() (scaled proportionally)
# Scatter Plot X/Y In the same proportion
ggplot(mpg, aes(cty, hwy)) +
geom_point() +
coord_fixed(ratio = 1) # 1:1 Ratio
(4) Coordinate Axis Transformation
# log Transformation
ggplot(df, aes(x, y)) + geom_point() + scale_y_log10()
# Square Root Transformation
ggplot(df, aes(x, y)) + geom_point() + scale_y_sqrt()
8. Comments and Text
(1) geom_text() / geom_label()
# Add labels next to the data points
ggplot(df, aes(x, y)) +
geom_point() +
geom_text(aes(label = name), vjust = -0.5)
# Add a circular label
ggplot(df, aes(x, y)) +
geom_point() +
geom_label(aes(label = name))
(2) annotate() Manual Annotation
# Mark Key Points
ggplot(df, aes(x, y)) +
geom_point() +
annotate("text", x = 5, y = 8, label = "Key Points", color = "red") +
annotate("rect", xmin = 4, xmax = 6, ymin = 7, ymax = 9,
alpha = 0.2, fill = "yellow")
(3) Arrow
library(ggrepel)
# "Auto-Skip" tag
ggplot(df, aes(x, y, label = name)) +
geom_point() +
geom_text_repel() # Non-overlapping tags
9. Combining Multiple Images
(1) Patchwork Bag
# Installation
install.packages("patchwork")
library(patchwork)
# 4 Image Collage 1
(p1 + p2) / (p3 + p4) # 2 row 2 col
# Complex Layout
p1 + p2 + p3 + p4 + plot_layout(ncol = 2, heights = c(2, 1))
# Add a title
(p1 + p2) / (p3 + p4) + plot_annotation(title = "Comprehensive Analysis")
(2) cowplot Package
library(cowplot)
plot_grid(p1, p2, p3, p4, ncol = 2, labels = c("A", "B", "C", "D"))
10. Complete Example: 4 Cities × 4 Products—Multidimensional Analysis
Below is an example of a complete workflow that ties together all the advanced features covered in this lesson.
▶ Example: Comprehensive Visualization of Multidimensional Sales Data
# ============================================
# 4 City × 4 Products Multidimensional Sales Analysis
# Features:Sub-section + Trendline + Notes + Multi-Image Collage
# ============================================
library(ggplot2)
library(dplyr)
library(tidyr)
library(patchwork)
# 1. Prepare data
sales <- expand_grid(
city = c("Beijing", "Shanghai", "Guangzhou", "Shenzhen"),
quarter = c("Q1", "Q2", "Q3", "Q4"),
product = c("Cell Phone", "Computer", "Tablet", "Headphones")
) |>
mutate(sales = round(runif(64, 500, 3000)))
cat("=== Data Volume:", nrow(sales), "row ===\n")
print(head(sales, 5))
# 2. Plot 1:4 Overall Urban Trends(Basics)
p1 <- ggplot(sales, aes(x = quarter, y = sales, color = city, group = city)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
labs(title = "4 Overall Sales Trends by City", color = "City") +
theme_minimal() +
theme(legend.position = "bottom")
# 3. Plot 2:By City(facet_wrap)
p2 <- ggplot(sales, aes(x = quarter, y = sales, color = product, group = product)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
facet_wrap(~ city, nrow = 2) +
labs(title = "Product Sales by City", color = "Products") +
theme_minimal() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 45, hjust = 1))
# 4. Plot 3:By City(By Product Stack)
p3 <- ggplot(sales, aes(x = quarter, y = sales, fill = product)) +
geom_col(position = "stack") +
facet_wrap(~ city, nrow = 2) +
labs(title = "Product Bundle Sales by City", fill = "Products") +
scale_fill_brewer(palette = "Set2") +
theme_minimal() +
theme(legend.position = "bottom")
# 5. Plot 4:Trendline + Original Point
p4 <- ggplot(sales, aes(x = quarter, y = sales, color = city, group = city)) +
geom_point(alpha = 0.3) +
geom_smooth(method = "lm", se = TRUE) +
labs(title = "Linear Trendline + Confidence Interval") +
theme_minimal() +
theme(legend.position = "bottom")
# 6. Plot 5:Box-and-Whisker Plots
p5 <- ggplot(sales, aes(x = product, y = sales, fill = product)) +
geom_boxplot() +
labs(title = "Sales Breakdown by Product") +
theme_minimal() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1))
# 7. Plot 6:Heat Map(geom_tile)
sales_summary <- sales |>
group_by(city, product) |>
summarise(total = sum(sales), .groups = "drop")
p6 <- ggplot(sales_summary, aes(x = city, y = product, fill = total)) +
geom_tile() +
geom_text(aes(label = total), color = "white") +
labs(title = "City × Products Total Sales Heat Map", fill = "Total Sales") +
scale_fill_gradient(low = "lightblue", high = "darkred") +
theme_minimal()
# 8. Multi-Image Collage(patchwork)
combined <- (p1 + p2) / (p3 + p4) / (p5 + p6) +
plot_annotation(
title = "4 City × 4 Products Comprehensive Sales Analysis",
subtitle = "Data Simulation | ggplot2 Photo Gallery"
)
print(combined)
# 9. Save as high resolution PNG
ggsave("multi_dimension_analysis.png", combined,
width = 16, height = 18, dpi = 300)
cat("\n=== The composite image has been saved:multi_dimension_analysis.png ===\n")
Expected output: A large image composed of 6 subimages (arranged in a 3×2 grid using the "patchwork" method).
❓ FAQ
facet_wrap and facet_grid?facet_wrap(~ var) One-dimensional faceting (automatic line breaks), facet_grid(rows ~ cols) Two-dimensional faceting (fixed rows and columns).geom_smooth?method = "lm".theme(strip.background = element_blank()) (remove background) + theme(strip.text = element_text(color = "red")) (change text color).p1 + p2 for side-by-side, p1 / p2 for top-and-bottom, (p1 + p2) / (p3 + p4) for 2x2. Use plot_layout(ncol = 2) for complex layouts.ggrepel to wrap geom_text_repel() / geom_label_repel(), and it will automatically avoid the data points.coord_flip Rotates by 90 degrees (horizontal chart), coord_polar Converts to polar coordinates (pie chart/rose chart).📖 Summary
- ggplot2 7-layer syntax: data/aesthetics/geometry/statistics/coordinates/facets/themes
- Use
+for layering, stacking from bottom to top - Facing:
facet_wrap(~ var)One-dimensional /facet_grid(rows ~ cols)Two-dimensional geom_smooth()Automatically Add Trendlines (LOESS/lm)stat_summary()Add statistical layers such as the mean and error bars- Coordinate transformations:
coord_flipFlip /coord_polarPolar coordinates /scale_y_log10Logarithmic transformation - Notes:
geom_textData label /annotateManual annotation /ggrepelAutomatic avoidance - Multiple-image set:
patchworkpackage (Recommended) /cowplotpackage - ggplot2 for Advanced Users = The Art of Combining Layers—Building Complex Plots from Simple Layers
📝 Exercises
-
Basic Exercise: Create a data frame (30 rows, 4 columns: x/y/group/category), use
facet_wrap(~ group)to plot a scatter plot, and verify the slicing effect; then usefacet_grid(group ~ category)to plot a two-dimensional slice. -
Basic Exercise: Using
mtcars, plot a scatter plot ofwtvs.mpg, add a trendline forgeom_smooth(method = "lm"), and draw a quadratic curve forgeom_smooth(method = "lm", formula = y ~ poly(x, 2), color = "red"), then compare the two fits. -
Basic Exercise: Draw a bar chart (with 5 categories), use
coord_flip()to rotate it horizontally, then usecoord_polar()to convert it to a pie chart, and compare the differences. -
Advanced Exercise: Construct 3-dimensional data (x/y/group), use ggplot2 to plot three cross-sectional plots (
facet_wrap), and finally usepatchworkto combine them into a 1x3 horizontal combination plot with a summary title. -
Challenge: Comprehensive Challenge—Create 1 "publication-quality" composite chart: ① Using
mtcars4-dimensional data (wt/mpg/cyl/hp) ② Usingfacet_wrap(~ cyl)to segment by number of cylinders ③ Add a LOESS trendline ④ Useggrepelto highlight the top 3 and bottom 3 vehicles ⑤ Usepatchworkto add a box plot for reference ⑥ Save as a high-resolution PNG.