R ggplot2 数据可视化:图层语法与常用图表
ggplot2 是 R 最强大的绘图包,基于图层语法(Grammar of Graphics):数据、映射、几何对象、统计变换、坐标、分面、主题,逐层叠加成图。
1. 基本原理
library(ggplot2)
# 一张图的骨架
ggplot(data = 数据集, aes(x = 变量, y = 变量)) +
geom_xxx() + # 几何图层(点/线/柱/箱线...)
labs(...) + # 标签
theme_xxx() # 主题
data:数据框aes():美学映射(x、y、color、fill、size、shape)geom_*:几何对象,每层一个
2. 内置数据集快速上手
# mpg:汽车油耗数据;iris:鸢尾花数据
head(mpg)
head(iris)
2.1 散点图(scatter)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# 按类别着色 + 平滑趋势线
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(size = 2, alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE, color = "black", linewidth = 0.6)
2.2 箱线图(boxplot)
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
geom_boxplot() +
geom_jitter(width = 0.2, size = 1, alpha = 0.5) # 叠加散点展示分布
2.3 直方图(histogram)
ggplot(iris, aes(x = Petal.Length)) +
geom_histogram(bins = 30, fill = "steelblue", color = "white")
2.4 柱状图(bar)
# 计数柱状图
ggplot(mpg, aes(x = class)) +
geom_bar()
# 数值柱状图(需要先聚合)
library(dplyr)
avg_hwy <- mpg %>%
group_by(class) %>%
summarise(mean_hwy = mean(hwy), .groups = "drop")
ggplot(avg_hwy, aes(x = reorder(class, mean_hwy), y = mean_hwy)) +
geom_col(fill = "#3b82f6") +
coord_flip() # 横置,长类别名更易读
2.5 折线图(line)
# 时间序列示例
df <- data.frame(
time = seq(0, 20, by = 2),
value = sin(seq(0, 20, by = 2)) + rnorm(11, 0, 0.1)
)
ggplot(df, aes(x = time, y = value)) +
geom_line(linewidth = 1, color = "#3b82f6") +
geom_point(size = 2)
3. 分面(facet)
按变量拆分成多个子图:
# 按 drv 分面:一排
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~drv)
# 双变量分面:网格
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(cyl ~ drv)
4. 颜色主题
4.1 标度控制(scale)
# 连续色阶
ggplot(mpg, aes(x = displ, y = hwy, color = year)) +
geom_point() +
scale_color_gradient(low = "blue", high = "red")
# 离散色板
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point(size = 2.5) +
scale_color_brewer(palette = "Set1") # 内置 RColorBrewer 色板
# 手动指定
scale_color_manual(values = c("#3b82f6", "#10b981", "#f59e0b"))
4.2 主题美化
p <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point(size = 2.5)
# 经典白底主题
p + theme_bw()
# 极简主题
p + theme_minimal()
# 自定义细节
p +
theme_minimal(base_size = 14) +
theme(
legend.position = "top", # 图例位置
panel.grid.minor = element_blank(), # 去掉次要网格线
plot.title = element_text(face = "bold", size = 16)
)
5. 标签与导出
p <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point(size = 2.5) +
labs(
title = "鸢尾花测量数据",
subtitle = "Sepal 尺寸分布",
x = "花萼长度 (cm)",
y = "花萼宽度 (cm)",
color = "物种"
) +
theme_minimal()
# 保存:ggsave 自动识别扩展名
ggsave("iris_scatter.png", p, width = 8, height = 6, dpi = 300)
ggsave("iris_scatter.pdf", p, width = 8, height = 6)
论文投稿建议导出 PDF 矢量图(300 dpi 的 PNG 用于网页)。
6. 生物信息学实战:火山图
差异表达分析的标准可视化:
# 模拟差异表达结果
set.seed(42)
de <- data.frame(
gene = paste0("GENE", 1:500),
log2fc = rnorm(500, 0, 1.8),
pvalue = runif(500, 0, 1)
)
# 标记显著基因
de <- de %>%
mutate(significance = case_when(
abs(log2fc) > 1 & pvalue < 0.05 ~ "up/down",
pvalue < 0.05 ~ "significant",
TRUE ~ "ns"
))
ggplot(de, aes(x = log2fc, y = -log10(pvalue), color = significance)) +
geom_point(size = 1.5, alpha = 0.6) +
scale_color_manual(values = c("up/down" = "#ef4444", "significant" = "#3b82f6", "ns" = "#9ca3af")) +
geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "gray50") +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "gray50") +
labs(title = "差异表达火山图", x = "log2 Fold Change", y = "-log10(p-value)") +
theme_minimal()
7. 小结
- 图层语法:
ggplot(data, aes()) + geom_xxx() + labs() + theme_xxx() - 常用几何:
geom_point/geom_boxplot/geom_histogram/geom_col/geom_line - 分组用
aes(color/fill),拆图用facet_wrap/facet_grid - 主题
theme_minimal+labs+ggsave(dpi=300)即出版级输出
至此 R 教程三部曲完成:入门 → tidyverse → ggplot2。