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



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

R
# 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

100%
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

R
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
▶ Try it Yourself
💡 Tip: Add a layer for each + 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:

R
# 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

R
# 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")
R
# 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

R
# 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

R
# 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

R
# 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

R
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

R
# 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

R
# 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

R
# Horizontal Bar Chart
ggplot(df, aes(x = city, y = sales)) +
  geom_col() +
  coord_flip()  # x/y Swap

(2) coord_polar() Polar Coordinates

R
# 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)

R
# 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

R
# 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()

R
# 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

R
# 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

R
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

R
# 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

R
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

R 📖 Display only
# ============================================
# 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")
63 logic lines (exceeds 40-line limit, display only)

Expected output: A large image composed of 6 subimages (arranged in a 3×2 grid using the "patchwork" method).


❓ FAQ

Q What is the difference between facet_wrap and facet_grid?
A facet_wrap(~ var) One-dimensional faceting (automatic line breaks), facet_grid(rows ~ cols) Two-dimensional faceting (fixed rows and columns).
Q What is the default setting for geom_smooth?
A The default is LOESS smoothing (n < 1000) or GAM (n ≥ 1000). To use linear regression, add method = "lm".
Q How do I remove the background from the page labels?
A theme(strip.background = element_blank()) (remove background) + theme(strip.text = element_text(color = "red")) (change text color).
Q How do I use "patchwork"?
A 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.
Q How can I add text labels without them overlapping?
A Use ggrepel to wrap geom_text_repel() / geom_label_repel(), and it will automatically avoid the data points.
Q What's the difference between coord_polar and coord_flip?
A coord_flip Rotates by 90 degrees (horizontal chart), coord_polar Converts to polar coordinates (pie chart/rose chart).

📖 Summary


📝 Exercises

  1. 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 use facet_grid(group ~ category) to plot a two-dimensional slice.

  2. Basic Exercise: Using mtcars, plot a scatter plot of wt vs. mpg, add a trendline for geom_smooth(method = "lm"), and draw a quadratic curve for geom_smooth(method = "lm", formula = y ~ poly(x, 2), color = "red"), then compare the two fits.

  3. Basic Exercise: Draw a bar chart (with 5 categories), use coord_flip() to rotate it horizontally, then use coord_polar() to convert it to a pie chart, and compare the differences.

  4. Advanced Exercise: Construct 3-dimensional data (x/y/group), use ggplot2 to plot three cross-sectional plots (facet_wrap), and finally use patchwork to combine them into a 1x3 horizontal combination plot with a summary title.

  5. Challenge: Comprehensive Challenge—Create 1 "publication-quality" composite chart: ① Using mtcars 4-dimensional data (wt/mpg/cyl/hp) ② Using facet_wrap(~ cyl) to segment by number of cylinders ③ Add a LOESS trendline ④ Use ggrepel to highlight the top 3 and bottom 3 vehicles ⑤ Use patchwork to add a box plot for reference ⑥ Save as a high-resolution PNG.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏