数据可视化是数据分析中最直观、最有效的沟通方式。一张好的图表胜过千言万语,能够帮助我们发现数据中的模式、趋势和异常。R语言拥有强大的可视化生态系统,从基础绘图到现代的ggplot2,从静态图表到交互式可视化,应有尽有。
本教程将系统介绍R语言数据可视化的各项技术,帮助你创建专业、美观、有效的数据可视化作品。
本教程的建议学习方法:先阅读并理解前四章内容即可,后面的内容可以在需要使用的时候再看,但依然建议粗略浏览以获得大致印象
本教程涵盖以下内容:
| 小节 | 内容 | 链接 |
|---|---|---|
| 1.1 | R可视化生态系统简介 | 概述 |
| 1.2 | 基础绘图系统核心思想 | 画家模式 |
| 1.3 | 高级绘图函数 | plot/hist/boxplot/barplot |
| 1.4 | 低级绘图函数 | points/lines/text/legend |
| 1.5 | 图形参数设置 | par()参数 |
| 1.6 | 基础图形布局 | layout()布局 |
| 1.7 | 保存基础图形 | pdf/png/jpeg |
| 1.8 | 基础绘图的局限性与转型至ggplot2 | 转型建议 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 2.1 | ggplot2的安装与加载 | 入门 |
| 2.2 | 图形语法核心理念 | 图层概念 |
| 2.3 | ggplot()函数与数据映射 | aes()映射 |
| 2.4 | 几何对象 | geom_*函数 |
| 2.5 | 统计变换 | stat_*变换 |
| 2.6 | 标度概述 | scale_*标度 |
| 2.7 | 坐标系概述 | coord_*坐标系 |
| 2.8 | 分面概述 | facet_*分面 |
| 2.9 | 主题概述 | theme()主题 |
| 2.10 | 使用+符号构建图形 | 图层叠加 |
| 小节 | 图形类型 | 链接 |
|---|---|---|
| 3.1 | 散点图 | geom_point() |
| 3.2 | 折线图 | geom_line() |
| 3.3 | 柱状图 | geom_bar()/geom_col() |
| 3.4 | 直方图 | geom_histogram() |
| 3.5 | 密度图 | geom_density() |
| 3.6 | 箱线图 | geom_boxplot() |
| 3.7 | 小提琴图 | geom_violin() |
| 3.8 | 点图 | geom_dotplot() |
| 3.9 | 面积图 | geom_area() |
| 3.10 | 饼图 | coord_polar() |
| 3.11 | 误差条 | geom_errorbar() |
| 3.12 | 平滑曲线 | geom_smooth() |
| 3.13 | 分位图 | geom_quantile() |
| 3.14 | 文本注释 | geom_text()/geom_label() |
| 3.15 | 热图 | geom_tile() |
| 小节 | 内容 | 链接 |
|---|---|---|
| 4.1 | 颜色标度 | scale_color_* |
| 4.2 | 形状标度 | scale_shape_* |
| 4.3 | 大小标度 | scale_size_* |
| 4.4 | 线条类型标度 | scale_linetype_* |
| 4.5 | 透明度标度 | scale_alpha_* |
| 4.6 | 坐标轴标度 | scale_x/y_* |
| 4.7 | 日期轴标度 | scale_x_date() |
| 4.8 | 手动设定标度 | scale_*_manual() |
| 4.9 | 坐标轴变换 | scale_*_log10/trans |
| 4.10 | 图例与标题的调整 | guides()/labs() |
| 小节 | 内容 | 链接 |
|---|---|---|
| 5.1 | 笛卡尔坐标系 | coord_cartesian() |
| 5.2 | 固定纵横比 | coord_fixed() |
| 5.3 | 极坐标系 | coord_polar() |
| 5.4 | 翻转坐标系 | coord_flip() |
| 5.5 | 地图投影 | coord_map() |
| 5.6 | 分面基础:facet_wrap | 一维分面 |
| 5.7 | 分面进阶:facet_grid | 二维分面 |
| 5.8 | 分面中的标度自由设定 | scales参数 |
| 5.9 | 分面标签与间距调整 | labeller参数 |
| 5.10 | 嵌套分面 | facet_nested() |
| 小节 | 内容 | 链接 |
|---|---|---|
| 6.1 | 内置主题 | theme_bw/gray/minimal |
| 6.2 | 主题元素调整 | element_*函数 |
| 6.3 | 文本元素 | element_text() |
| 6.4 | 矩形元素 | element_rect() |
| 6.5 | 线条元素 | element_line() |
| 6.6 | 图例位置与样式 | legend.position |
| 6.7 | 间距与边距 | margin/plot.margin |
| 6.8 | 自定义完整主题 | theme()函数 |
| 6.9 | 扩展包主题 | ggthemes/hrbrthemes |
| 小节 | 内容 | 链接 |
|---|---|---|
| 7.1 | 基础多图:par(mfrow) | 基础方法 |
| 7.2 | 网格布局:gridExtra | grid.arrange() |
| 7.3 | cowplot包 | plot_grid() |
| 7.4 | patchwork包 | +/|操作符 |
| 7.5 | 插入子图 | inset plot |
| 7.6 | 共用图例与轴 | get_legend() |
| 7.7 | 复杂布局设计 | area()布局 |
| 7.8 | 多页PDF输出 | pdf()设备 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 8.1 | RColorBrewer调色板 | 配色方案 |
| 8.2 | viridis色系 | 色盲友好配色 |
| 8.3 | 自定义颜色向量 | colorRampPalette() |
| 8.4 | 渐变色自定义 | scale_*_gradient() |
| 8.5 | 字体设置 | showtext包 |
| 8.6 | 使用系统字体 | extrafont包 |
| 8.7 | 标注与文本注释的高级用法 | annotate()/geom_text() |
| 8.8 | 数学表达式与公式标注 | expression() |
| 8.9 | 表格嵌入图形 | gridExtra/tableGrob |
| 小节 | 内容 | 链接 |
|---|---|---|
| 9.1 | plotly包基础 | ggplotly() |
| 9.2 | plotly原生语法 | plot_ly() |
| 9.3 | 悬停信息定制 | tooltip定制 |
| 9.4 | 缩放、平移、框选交互 | 交互模式 |
| 9.5 | highcharter包 | 高级交互图表 |
| 9.6 | echarts4r包 | ECharts绑定 |
| 9.7 | ggiraph包 | 交互式ggplot |
| 9.8 | shiny中的可视化集成 | 动态可视化 |
| 9.9 | 交互式时间序列 | dygraphs包 |
| 9.10 | 交互式网络图 | visNetwork包 |
| 小节 | 图形类型 | 链接 |
|---|---|---|
| 10.1 | 统计分布图 | geom_density_ridges() |
| 10.2 | 二维密度图 | geom_density_2d() |
| 10.3 | 六边形热图 | geom_hex() |
| 10.4 | 韦恩图/欧拉图 | VennDiagram/eulerr |
| 10.5 | 词云 | wordcloud包 |
| 10.6 | 雷达图/蜘蛛图 | fmsb包 |
| 10.7 | 平行坐标图 | GGally包 |
| 10.8 | 瀑布图 | waterfalls包 |
| 10.9 | 相关系数矩阵图 | corrplot包 |
| 10.10 | 热图聚类 | pheatmap包 |
| 10.11 | 树状图 | ggdendro包 |
| 10.12 | 时间序列分解图 | forecast包 |
| 10.13 | 生存曲线图 | survminer包 |
| 10.14 | 森林图 | forestplot包 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 11.1 | gganimate基础 | transition_*函数 |
| 11.2 | 过渡效果 | transition_states() |
| 11.3 | 出现与消失 | enter/exit函数 |
| 11.4 | 视图过渡 | view_*函数 |
| 11.5 | 影子效果 | shadow_*函数 |
| 11.6 | 缓动函数 | ease_aes() |
| 11.7 | tweenr平滑过渡 | 插值动画 |
| 11.8 | transformr几何变换 | 形状变换 |
| 11.9 | 动画渲染设置 | animate()参数 |
| 11.10 | 复杂动画案例 | 综合示例 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 12.1 | sf包基础 | 简单要素 |
| 12.2 | ggplot2绘制简单地图 | geom_sf() |
| 12.3 | 从外部读取地图数据 | rnaturalearth/maps |
| 12.4 | 地图数据可视化 | 填充地图 |
| 12.5 | 分层地图 | 多图层叠加 |
| 12.6 | 交互式地图:leaflet | leaflet包 |
| 12.7 | 地图投影变换 | coord_sf() |
| 12.8 | 地理数据聚合 | 空间聚合 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 13.1 | igraph基础 | 网络对象创建 |
| 13.2 | ggraph网络图 | geom_edge_* |
| 13.3 | 节点与边的美学 | 节点/边样式 |
| 13.4 | 网络布局算法 | layout参数 |
| 13.5 | 层次结构树状图 | dendrogram |
| 13.6 | 树状图定制 | ggraph树图 |
| 小节 | 图形类型 | 链接 |
|---|---|---|
| 14.1 | 回归诊断图 | plot(lm) |
| 14.2 | 残差分析可视化 | 残差图 |
| 14.3 | 随机森林变量重要性图 | varImpPlot() |
| 14.4 | 混淆矩阵可视化 | confusionMatrix图 |
| 14.5 | ROC曲线与AUC | pROC包 |
| 14.6 | 生存曲线 | survfit()图 |
| 14.7 | 模型预测对比图 | 预测值vs实际值 |
| 14.8 | 贝叶斯模型后验分布图 | bayesplot包 |
| 小节 | 内容 | 链接 |
|---|---|---|
| 15.1 | 大数据集可视化策略 | 采样/聚合策略 |
| 15.2 | geom_point的透明度与光栅化 | 透明度优化 |
| 15.3 | 使用data.table预先聚合 | 数据预处理 |
| 15.4 | 图形保存格式选择 | 矢量/位图格式 |
| 15.5 | 分辨率与尺寸设置 | DPI设置 |
| 15.6 | 可视化配色原则 | 配色建议 |
| 15.7 | 图标题、轴标签的清晰性 | 标签规范 |
| 15.8 | 避免信息冗余与图表垃圾 | 简洁原则 |
| 15.9 | 可重复性:脚本化图形生成 | 自动化流程 |
| 15.10 | 自定义函数封装常用图形模板 | 函数封装 |
在Rstudio中安装本节课所有需要的包,运行以下指令:
install.packages(c(
"ggplot2", "dplyr", "tidyr",
"gridExtra", "cowplot", "patchwork", "grid",
"RColorBrewer", "viridis",
"ggrepel",
"quantreg", "broom",
"plotly", "highcharter", "echarts4r", "ggiraph", "dygraphs",
"gganimate", "gapminder", "tweenr", "transformr",
"sf", "maps", "rnaturalearth",
"igraph", "ggraph", "ggforce",
"factoextra",
"randomForest",
"pROC",
"survival", "survminer",
"ggalluvial", "treemapify",
"ggforce"
))
R语言提供了两套主要的绘图系统:基础绘图系统(base graphics)和基于图形语法的ggplot2系统。本章介绍基础绘图系统,它是理解R可视化的起点。
R语言拥有丰富的可视化包和工具。
# R可视化的主要系统
# 1. 基础绘图系统(base graphics)
# R内置的绘图系统,简单直接
# 主要函数:plot()、hist()、boxplot()、barplot()等
# 2. lattice包
# 基于网格图形系统,适合多变量、多面板图形
# 主要函数:xyplot()、bwplot()、histogram()等
# 3. ggplot2包
# 基于图形语法(Grammar of Graphics),最流行的R可视化包
# 使用图层叠加的方式构建图形
# 4. 交互式可视化
# plotly:将ggplot2转为交互式
# highcharter:高级交互图表
# leaflet:交互式地图
# 5. 专用可视化
# 热图:pheatmap、ComplexHeatmap
# 网络图:igraph、ggraph
# 时间序列:forecast、dygraphs
小结:ggplot2是R可视化的主流选择,但基础绘图系统仍然重要。
基础绘图系统采用”画家模式”,逐步在画布上添加图形元素。
# 基础绘图的两种函数类型
# 1. 高级绘图函数:创建新图形
# 每次调用会创建新的图形窗口
# 例如:plot()、hist()、boxplot()、barplot()
# 2. 低级绘图函数:在现有图形上添加元素
# 在当前图形上添加内容,不会创建新图形
# 例如:points()、lines()、text()、legend()
# 示例:画家模式
# 创建示例数据
x <- 1:10
y <- x^2
# 第一步:创建基础图形
plot(x, y, type = "n", main = "画家模式示例") # type="n"只创建框架不画点
# 第二步:逐步添加元素
points(x, y, pch = 19, col = "blue") # 添加点
lines(x, y, col = "red") # 添加线
text(5, 50, "y = x^2", col = "darkgreen") # 添加文本
legend("topleft", legend = c("数据点", "连线"),
col = c("blue", "red"), pch = c(19, NA), lty = c(NA, 1))
小结:基础绘图系统像画家作画,逐步添加元素构建完整图形。
高级绘图函数创建新图形。
# plot()是最通用的高级绘图函数
# 创建示例数据
x <- 1:20
y <- rnorm(20)
# 基础散点图
plot(x, y)
# 指定标题和标签
plot(x, y,
main = "散点图示例", # 主标题
xlab = "X轴标签", # X轴标签
ylab = "Y轴标签", # Y轴标签
col = "steelblue", # 点的颜色
pch = 19, # 点的形状(实心圆)
cex = 1.5) # 点的大小
# 绘制函数曲线
curve(x^2, from = -5, to = 5, main = "y = x^2")
# 绘制折线图
plot(x, y, type = "l", main = "折线图") # type="l"表示线条
# 绘制点线图
plot(x, y, type = "b", main = "点线图") # type="b"表示点和线
# hist()绘制直方图
# 创建正态分布数据
data <- rnorm(1000, mean = 50, sd = 10)
# 基础直方图
hist(data)
# 自定义直方图
hist(data,
main = "正态分布数据直方图",
xlab = "数值",
ylab = "频数",
col = "lightblue",
breaks = 30, # 分组数量
border = "white", # 边框颜色
probability = TRUE) # 显示概率密度而非频数
# 添加密度曲线
lines(density(data), col = "red", lwd = 2)
# boxplot()绘制箱线图
# 创建分组数据
group_A <- rnorm(50, mean = 50, sd = 10)
group_B <- rnorm(50, mean = 60, sd = 15)
group_C <- rnorm(50, mean = 55, sd = 8)
# 基础箱线图
boxplot(group_A, group_B, group_C,
main = "三组数据对比",
names = c("组A", "组B", "组C"),
col = c("lightblue", "lightgreen", "lightpink"))
# 使用公式语法
df <- data.frame(
value = c(group_A, group_B, group_C),
group = factor(rep(c("A", "B", "C"), each = 50))
)
boxplot(value ~ group, data = df,
main = "按组分组箱线图",
xlab = "组别",
ylab = "数值",
col = c("lightblue", "lightgreen", "lightpink"))
# barplot()绘制柱状图
# 创建数据
categories <- c("产品A", "产品B", "产品C", "产品D")
sales <- c(150, 200, 120, 180)
# 基础柱状图
barplot(sales, names.arg = categories,
main = "产品销售额",
xlab = "产品",
ylab = "销售额",
col = "steelblue")
# 水平柱状图
barplot(sales, names.arg = categories,
main = "产品销售额(水平)",
horiz = TRUE, # 水平方向
col = "coral",
las = 1) # 标签方向
# 堆叠柱状图
sales_matrix <- matrix(c(100, 80, 70, 90,
50, 120, 50, 90),
nrow = 2, byrow = TRUE)
rownames(sales_matrix) <- c("上半年", "下半年")
colnames(sales_matrix) <- categories
barplot(sales_matrix,
main = "产品销售额对比",
col = c("lightblue", "lightgreen"),
legend.text = TRUE,
beside = FALSE) # beside=FALSE表示堆叠
# 分组柱状图
barplot(sales_matrix,
main = "产品销售额对比(分组)",
col = c("lightblue", "lightgreen"),
legend.text = TRUE,
beside = TRUE) # beside=TRUE表示分组
# pie()绘制饼图
# 创建数据
categories <- c("产品A", "产品B", "产品C", "产品D")
sales <- c(150, 200, 120, 180)
# 基础饼图
pie(sales, labels = categories,
main = "产品销售占比",
col = c("lightblue", "lightgreen", "lightpink", "lightyellow"))
# 显示百分比
percent <- round(sales / sum(sales) * 100, 1)
labels <- paste(categories, "\n", percent, "%", sep = "")
pie(sales, labels = labels,
main = "产品销售占比(带百分比)",
col = c("lightblue", "lightgreen", "lightpink", "lightyellow"))
小结:高级绘图函数创建新图形,常用参数包括main、xlab、ylab、col、pch等。
低级绘图函数在现有图形上添加元素。
# 创建基础图形
x <- 1:10
y <- x + rnorm(10)
plot(x, y, type = "n", main = "低级绘图函数示例",
xlab = "X", ylab = "Y", xlim = c(0, 11), ylim = c(-2, 12))
# points()添加点
points(x, y, pch = 19, col = "blue", cex = 1.5)
# lines()添加线
lines(x, x, col = "red", lwd = 2, lty = 2)
# abline()添加直线
abline(a = 0, b = 1, col = "green", lwd = 2) # y = x
abline(h = 5, col = "gray", lty = 2) # 水平线
abline(v = 5, col = "gray", lty = 3) # 垂直线
# text()添加文本
text(8, 2, "y = x", col = "green", cex = 1.2)
# legend()添加图例
legend("topleft",
legend = c("数据点", "拟合线", "y=x"),
col = c("blue", "red", "green"),
pch = c(19, NA, NA),
lty = c(NA, 2, 1),
lwd = c(NA, 2, 2))
# title()添加标题(如果需要后加)
title(sub = "副标题", col.sub = "gray")
# axis()添加坐标轴
# 在右侧添加坐标轴
axis(4, at = seq(0, 10, 2), labels = letters[1:6])
# mtext()在边距添加文本
mtext("右侧标注", side = 4, line = 2, col = "blue")
# polygon()添加多边形
polygon(c(2, 4, 4, 2), c(2, 2, 4, 4),
col = rgb(1, 0, 0, 0.3), border = "red")
# segments()添加线段
segments(6, 8, 8, 10, col = "purple", lwd = 2)
# arrows()添加箭头
arrows(6, 6, 8, 8, col = "orange", lwd = 2, length = 0.1)
小结:低级绘图函数可以灵活地在图形上添加各种元素。
使用par()函数设置全局图形参数。
# par()函数控制图形外观
# 查看当前参数设置
par("mfrow") # 图形布局
## [1] 1 1
par("mar") # 图形边距
## [1] 5.1 4.1 4.1 2.1
par("bg") # 背景色
## [1] "white"
# 设置多图布局
par(mfrow = c(2, 2)) # 2行2列
# 绘制4个图形
plot(1:10, main = "图1")
plot(10:1, main = "图2")
hist(rnorm(100), main = "图3")
boxplot(rnorm(100), main = "图4")
# 恢复默认设置
par(mfrow = c(1, 1))
# 设置边距
par(mar = c(5, 4, 4, 2) + 0.1) # 下、左、上、右
# 默认值:c(5, 4, 4, 2) + 0.1
# 设置外边距
par(oma = c(0, 0, 2, 0)) # 外边距
# 设置背景色
par(bg = "white")
# 设置字体大小
par(cex = 1.2) # 全局放大
par(cex.axis = 1) # 坐标轴
par(cex.lab = 1) # 标签
par(cex.main = 1.2) # 标题
# 设置颜色
par(col = "black") # 默认颜色
par(col.axis = "black") # 坐标轴颜色
par(col.lab = "black") # 标签颜色
par(col.main = "black") # 标题颜色
# 设置字体
par(family = "serif") # 衬线字体
# Windows下常用选项:"serif", "sans", "mono"
# 保存当前参数设置
old_par <- par(no.readonly = TRUE)
# 修改参数
par(mfrow = c(1, 2), mar = c(2, 2, 2, 2))
# 绘制图形
plot(1:10)
plot(10:1)
# 恢复原始参数
par(old_par)
小结:par()函数可以控制图形的各种全局参数,建议保存并恢复原始设置。
使用layout()函数创建复杂布局。
# layout()函数创建自定义布局
# 注意:如果加载了plotly包,需要使用graphics::layout()避免冲突
# 定义布局矩阵
# 0表示该位置不放置图形
layout_matrix <- matrix(c(1, 1, 2,
3, 3, 3,
4, 5, 5), nrow = 3, byrow = TRUE)
# 应用布局(使用graphics::layout避免与plotly冲突)
graphics::layout(layout_matrix)
# 设置边距
par(mar = c(2, 2, 2, 1))
# 绘制图形
plot(1:10, main = "图1(占2格)", col = "blue")
plot(1:10, main = "图2", col = "red")
hist(rnorm(100), main = "图3(占3格)", col = "green")
boxplot(rnorm(50), main = "图4", col = "purple")
pie(c(1, 2, 3), main = "图5(占2格)", col = c("red", "green", "blue"))
# 恢复默认布局
graphics::layout(1)
par(mar = c(5, 4, 4, 2) + 0.1)
# 查看布局
# layout.show(5) # 显示5个区域的布局
小结:layout()比par(mfrow)更灵活,可以创建不规则布局。注意plotly包也有layout()函数,需使用graphics::layout()区分。
将图形保存到文件。
# 保存为PDF
pdf("my_plot.pdf", width = 8, height = 6) # 打开PDF设备
plot(1:10, main = "保存的图形") # 绘制图形
dev.off() # 关闭设备
# 保存为PNG
png("my_plot.png", width = 800, height = 600, res = 100)
plot(1:10, main = "PNG图形")
dev.off()
# 保存为JPEG
jpeg("my_plot.jpg", width = 800, height = 600, quality = 90)
plot(1:10, main = "JPEG图形")
dev.off()
# 保存为SVG(矢量图)
svg("my_plot.svg", width = 8, height = 6)
plot(1:10, main = "SVG图形")
dev.off()
# 使用dev.copy()复制当前图形
plot(1:10, main = "当前图形")
dev.copy(pdf, "copied_plot.pdf")
dev.off()
# 查看当前设备
dev.cur()
# 查看所有设备
dev.list()
小结:矢量图(PDF、SVG)适合出版,位图(PNG、JPEG)适合网页。
基础绘图系统有一些局限性,ggplot2提供了更优雅的解决方案。
# 基础绘图的局限性
# 1. 代码冗长
# 基础绘图需要手动添加每个元素
par(mfrow = c(1, 2))
# 基础绘图方式
plot(1:10, (1:10)^2, type = "n", main = "基础绘图")
points(1:10, (1:10)^2, pch = 19, col = "blue")
lines(1:10, (1:10)^2, col = "red")
legend("topleft", legend = c("点", "线"),
pch = c(19, NA), lty = c(NA, 1),
col = c("blue", "red"))
# ggplot2方式(更简洁)
library(ggplot2)
df <- data.frame(x = 1:10, y = (1:10)^2)
ggplot(df, aes(x = x, y = y)) +
geom_point(color = "blue") +
geom_line(color = "red") +
ggtitle("ggplot2绘图") +
theme_minimal()
par(mfrow = c(1, 1))
# 2. 分组处理复杂
# 基础绘图需要循环处理分组
# ggplot2自动处理分组
# 3. 分面困难
# 基础绘图需要手动创建多个面板
# ggplot2的facet功能自动处理
# 4. 主题不统一
# 基础绘图需要手动设置每个元素
# ggplot2有内置主题系统
小结:ggplot2语法更简洁、更一致,是现代R可视化的首选。
ggplot2是R中最流行的可视化包,基于Leland Wilkinson的”图形语法”(Grammar of Graphics)理论。本章介绍ggplot2的核心概念和基本用法。
# 安装ggplot2(如果尚未安装)
# install.packages("ggplot2")
# 加载ggplot2
library(ggplot2)
# ggplot2是tidyverse的一部分
# 也可以加载整个tidyverse
# library(tidyverse)
# 查看ggplot2版本
packageVersion("ggplot2")
## [1] '4.0.2'
小结:ggplot2可以单独加载,也可以作为tidyverse的一部分加载。
图形语法将图形分解为独立的组件。
# 图形语法的核心组件
# 1. 数据(Data):要可视化的数据集
# 2. 映射(Aesthetics):数据变量到图形属性的映射
# 3. 几何对象(Geometries):图形的几何形状(点、线、柱等)
# 4. 标度(Scales):控制图形属性的映射方式
# 5. 坐标系(Coordinates):数据到平面的映射
# 6. 分面(Facets):将数据分割成多个子图
# 7. 主题(Theme):控制图形的非数据元素
# 示例:理解各组件
ggplot(data = mpg, # 数据
aes(x = displ, y = hwy)) + # 映射
geom_point() + # 几何对象
scale_x_continuous() + # 标度
coord_cartesian() + # 坐标系
facet_wrap(~ class) + # 分面
theme_minimal() # 主题
小结:图形语法将图形分解为独立组件,每个组件都可以单独调整。
ggplot()是所有ggplot2图形的起点。
# ggplot()函数的基本用法
# 创建基础图形对象(不显示图形)
p <- ggplot(data = mpg)
p
# 添加映射
p <- ggplot(data = mpg, aes(x = displ, y = hwy))
p
# 添加几何对象后才能显示图形
p + geom_point()
# 在geom_*()中添加映射
ggplot(data = mpg) +
geom_point(aes(x = displ, y = hwy))
# aes()中的映射
ggplot(data = mpg, aes(x = displ, y = hwy)) +
geom_point(aes(color = class)) # 颜色映射到class变量
# 在ggplot()和geom_*()中都可以设置映射
# ggplot()中的映射是全局的,对所有图层生效
# geom_*()中的映射只对该图层生效
# 示例:全局映射 vs 局部映射
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) # 平滑线也按颜色分组
## `geom_smooth()` using formula = 'y ~ x'
# 只在点图层使用颜色映射
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(aes(color = class)) +
geom_smooth(method = "lm", se = FALSE, color = "black") # 只有一条平滑线
## `geom_smooth()` using formula = 'y ~ x'
小结:ggplot()创建图形对象,aes()定义数据到图形属性的映射。
几何对象定义图形的形状。
# 常用几何对象
# geom_point():散点图
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# geom_line():折线图
ggplot(economics, aes(x = date, y = unemploy)) +
geom_line()
# geom_bar():柱状图(自动计数)
ggplot(mpg, aes(x = class)) +
geom_bar()
# geom_col():柱状图(使用提供的y值)
df <- data.frame(
category = c("A", "B", "C"),
value = c(10, 20, 15)
)
ggplot(df, aes(x = category, y = value)) +
geom_col()
# geom_histogram():直方图
ggplot(mpg, aes(x = hwy)) +
geom_histogram(bins = 20)
# geom_density():密度图
ggplot(mpg, aes(x = hwy)) +
geom_density()
# geom_boxplot():箱线图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot()
# geom_violin():小提琴图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_violin()
# geom_smooth():平滑曲线
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
# geom_text():文本标签
ggplot(mpg[1:20, ], aes(x = displ, y = hwy)) +
geom_point() +
geom_text(aes(label = manufacturer), vjust = -0.5, size = 3)
# 组合多个几何对象
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(aes(color = class)) +
geom_smooth(method = "lm", se = TRUE) +
geom_rug() # 边缘地毯图
## `geom_smooth()` using formula = 'y ~ x'
小结:几何对象是图形的核心,可以通过+叠加多个图层。
统计变换对数据进行计算后绘图。
# 统计变换示例
# stat_summary():汇总统计
ggplot(mpg, aes(x = class, y = hwy)) +
stat_summary(fun = mean, geom = "point", size = 3, color = "red") +
stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width = 0.2)
# stat_smooth():平滑曲线(geom_smooth()的底层)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
stat_smooth(method = "lm")
## `geom_smooth()` using formula = 'y ~ x'
# stat_density():密度估计
ggplot(mpg, aes(x = hwy)) +
stat_density(geom = "line")
# stat_bin():分箱计数(geom_histogram()的底层)
ggplot(mpg, aes(x = hwy)) +
stat_bin(geom = "bar", bins = 20)
# stat_identity():直接使用数据值
df <- data.frame(x = 1:5, y = c(10, 20, 15, 25, 18))
ggplot(df, aes(x = x, y = y)) +
stat_identity(geom = "bar")
小结:统计变换在绘图前对数据进行计算,每个geom都有对应的stat。
标度控制数据到图形属性的映射。
# 标度控制图形属性
# 颜色标度
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
scale_color_brewer(palette = "Set1") # 使用ColorBrewer调色板
# 填充标度
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar() +
scale_fill_brewer(palette = "Set2")
# 大小标度
ggplot(mpg, aes(x = displ, y = hwy, size = cyl)) +
geom_point() +
scale_size(range = c(1, 5))
# 形状标度
ggplot(mpg, aes(x = displ, y = hwy, shape = drv)) +
geom_point() +
scale_shape_manual(values = c(16, 17, 18))
# 坐标轴标度
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(limits = c(0, 8), breaks = seq(0, 8, 2)) +
scale_y_continuous(limits = c(0, 50))
小结:标度函数以scale_开头,控制数据到图形属性的映射方式。
坐标系定义数据到平面的映射。
# 常用坐标系
# coord_cartesian():笛卡尔坐标系(默认)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_cartesian(xlim = c(2, 6), ylim = c(20, 40)) # 缩放视图但不删除数据
# coord_flip():翻转坐标系
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
coord_flip()
# coord_polar():极坐标系
ggplot(mpg, aes(x = factor(1), fill = class)) +
geom_bar(width = 1) +
coord_polar(theta = "y") # 饼图
# coord_fixed():固定纵横比
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_fixed(ratio = 1) # x轴和y轴单位长度相同
# coord_trans():坐标变换
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_trans(x = "log10", y = "log10")
## Warning: `coord_trans()` was deprecated in ggplot2 4.0.0.
## ℹ Please use `coord_transform()` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
小结:坐标系函数以coord_开头,控制数据到平面的映射方式。
分面将数据分割成多个子图。
# 分面类型
# facet_wrap():按单变量分面
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, ncol = 4) # 按class分面,4列
# facet_grid():按双变量分面
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl) # 行按drv,列按cyl
# 分面参数
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class,
ncol = 3, # 列数
scales = "free", # 各面板坐标轴独立
labeller = label_both) # 标签格式
小结:分面函数以facet_开头,用于创建多面板图形。
主题控制图形的非数据元素。
# 内置主题
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# theme_gray():默认灰色主题
p + theme_gray()
# theme_bw():黑白主题
p + theme_bw()
# theme_classic():经典主题
p + theme_classic()
# theme_minimal():极简主题
p + theme_minimal()
# theme_dark():深色主题
p + theme_dark()
# theme_void():空白主题
p + theme_void()
# theme_light():浅色主题
p + theme_light()
小结:主题控制图形的外观,ggplot2提供多种内置主题。
ggplot2使用+符号组合各组件。
# 使用+构建复杂图形
ggplot(mpg, aes(x = displ, y = hwy)) +
# 图层1:散点图
geom_point(aes(color = class, size = cyl), alpha = 0.6) +
# 图层2:平滑曲线
geom_smooth(method = "lm", se = TRUE, color = "black") +
# 标度
scale_color_brewer(palette = "Set1") +
scale_size_continuous(range = c(1, 4)) +
# 坐标轴标签
labs(
title = "发动机排量与高速公路油耗关系",
subtitle = "按车型分类",
x = "发动机排量 (L)",
y = "高速公路油耗 (mpg)",
color = "车型",
size = "气缸数"
) +
# 主题
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
legend.position = "right"
)
## `geom_smooth()` using formula = 'y ~ x'
小结:+符号将图形组件组合在一起,构建复杂图形。
本章介绍ggplot2中常用的统计图形,包括散点图、折线图、柱状图、直方图等。
散点图用于展示两个连续变量之间的关系。
# 基础散点图
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# 添加颜色映射
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point()
# 添加大小映射
ggplot(mpg, aes(x = displ, y = hwy, color = class, size = cyl)) +
geom_point()
# 设置透明度(处理重叠点)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.3)
# 使用形状区分组别
ggplot(mpg, aes(x = displ, y = hwy, shape = drv, color = drv)) +
geom_point(size = 2)
# 添加文本标签
ggplot(mpg[1:30, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_text(vjust = -0.5, size = 3)
# 使用geom_label()添加带背景的标签
ggplot(mpg[1:20, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_label(vjust = -0.5, size = 3, alpha = 0.7)
# 散点图矩阵(使用GGally包)
# library(GGally)
# ggpairs(mpg[, c("displ", "hwy", "cty", "cyl")])
小结:散点图是最常用的图形之一,可以通过颜色、大小、形状展示多维信息。
折线图用于展示数据随时间或有序变量的变化趋势。
# 基础折线图
ggplot(economics, aes(x = date, y = unemploy)) +
geom_line()
# 多条折线
ggplot(economics_long, aes(x = date, y = value01, color = variable)) +
geom_line()
# 添加点
ggplot(economics[1:50, ], aes(x = date, y = unemploy)) +
geom_line() +
geom_point()
# 阶梯图
df <- data.frame(
x = 1:10,
y = c(1, 1, 2, 2, 3, 3, 4, 4, 5, 5)
)
ggplot(df, aes(x = x, y = y)) +
geom_step()
# 面积图
ggplot(economics, aes(x = date, y = unemploy)) +
geom_area(fill = "steelblue", alpha = 0.5)
# 堆叠面积图
ggplot(economics_long[1:200, ], aes(x = date, y = value01, fill = variable)) +
geom_area(alpha = 0.5)
小结:折线图适合时间序列数据,可以展示趋势和变化。
柱状图用于展示分类变量的频数或数值。
# geom_bar():自动计数
ggplot(mpg, aes(x = class)) +
geom_bar()
# 添加颜色
ggplot(mpg, aes(x = class, fill = class)) +
geom_bar() +
theme(legend.position = "none")
# 堆叠柱状图
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar()
# 分组柱状图
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar(position = "dodge")
# 百分比堆叠柱状图
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar(position = "fill") +
ylab("比例")
# geom_col():使用提供的y值
df <- data.frame(
category = c("A", "B", "C", "D"),
value = c(10, 25, 15, 30)
)
ggplot(df, aes(x = category, y = value)) +
geom_col(fill = "steelblue")
# 水平柱状图
ggplot(df, aes(x = category, y = value)) +
geom_col(fill = "steelblue") +
coord_flip()
# 添加数值标签
ggplot(df, aes(x = category, y = value)) +
geom_col(fill = "steelblue") +
geom_text(aes(label = value), vjust = -0.5)
小结:geom_bar()自动计数,geom_col()使用提供的y值。
直方图用于展示连续变量的分布。
# 基础直方图
ggplot(mpg, aes(x = hwy)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value `binwidth`.
# 设置分组数量
ggplot(mpg, aes(x = hwy)) +
geom_histogram(bins = 20)
# 设置分组宽度
ggplot(mpg, aes(x = hwy)) +
geom_histogram(binwidth = 2)
# 添加颜色
ggplot(mpg, aes(x = hwy, fill = drv)) +
geom_histogram(bins = 20, position = "identity", alpha = 0.5)
# 堆叠直方图
ggplot(mpg, aes(x = hwy, fill = drv)) +
geom_histogram(bins = 20)
# 添加密度曲线
ggplot(mpg, aes(x = hwy)) +
geom_histogram(aes(y = after_stat(density)), bins = 20, fill = "steelblue") +
geom_density(color = "red", linewidth = 1)
小结:直方图展示数据分布,可通过bins或binwidth控制分组。
密度图是直方图的平滑版本。
# 基础密度图
ggplot(mpg, aes(x = hwy)) +
geom_density()
# 填充颜色
ggplot(mpg, aes(x = hwy)) +
geom_density(fill = "steelblue", alpha = 0.5)
# 按组绘制
ggplot(mpg, aes(x = hwy, fill = drv)) +
geom_density(alpha = 0.5)
# 直方图+密度图
ggplot(mpg, aes(x = hwy)) +
geom_histogram(aes(y = after_stat(density)), bins = 20,
fill = "lightgray", color = "white") +
geom_density(color = "red", linewidth = 1)
小结:密度图是直方图的平滑版本,适合比较多个分布。
箱线图用于展示数据分布和异常值。
# 基础箱线图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot()
# 添加颜色
ggplot(mpg, aes(x = class, y = hwy, fill = class)) +
geom_boxplot() +
theme(legend.position = "none")
# 水平箱线图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
coord_flip()
# 添加数据点
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
geom_jitter(width = 0.2, alpha = 0.3)
# 按组分组
ggplot(mpg, aes(x = drv, y = hwy, fill = factor(cyl))) +
geom_boxplot()
小结:箱线图展示数据分布的五数概括,适合比较多个组。
小提琴图结合了箱线图和密度图。
# 基础小提琴图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_violin()
# 添加箱线图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_violin() +
geom_boxplot(width = 0.1)
# 添加颜色
ggplot(mpg, aes(x = class, y = hwy, fill = class)) +
geom_violin() +
theme(legend.position = "none")
# 小提琴图+数据点
ggplot(mpg, aes(x = class, y = hwy, fill = class)) +
geom_violin(alpha = 0.5) +
geom_jitter(width = 0.2, alpha = 0.3) +
theme(legend.position = "none")
小结:小提琴图展示完整的分布形状,比箱线图信息更丰富。
点图用于展示各组的数值分布。
# 基础点图
ggplot(mpg, aes(x = hwy)) +
geom_dotplot()
## Bin width defaults to 1/30 of the range of the data. Pick better value with
## `binwidth`.
# 按组分组
ggplot(mpg, aes(x = class, y = hwy)) +
geom_dotplot(binaxis = "y", stackdir = "center")
## Bin width defaults to 1/30 of the range of the data. Pick better value with
## `binwidth`.
# 添加颜色
ggplot(mpg, aes(x = class, y = hwy, fill = class)) +
geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.5) +
theme(legend.position = "none")
## Bin width defaults to 1/30 of the range of the data. Pick better value with
## `binwidth`.
小结:点图适合展示小数据集的分布。
面积图强调数量随时间的变化。
# 基础面积图
ggplot(economics, aes(x = date, y = unemploy)) +
geom_area()
# 自定义颜色
ggplot(economics, aes(x = date, y = unemploy)) +
geom_area(fill = "steelblue", alpha = 0.5) +
geom_line(color = "steelblue")
# 堆叠面积图
ggplot(economics_long[1:200, ], aes(x = date, y = value01, fill = variable)) +
geom_area(alpha = 0.5)
小结:面积图强调数量变化,适合时间序列数据。
ggplot2通过极坐标创建饼图。
# 创建饼图
ggplot(mpg, aes(x = factor(1), fill = class)) +
geom_bar(width = 1) +
coord_polar(theta = "y") +
theme_void()
# 添加标签
df <- mpg %>%
count(class) %>%
mutate(prop = n / sum(n) * 100)
ggplot(df, aes(x = "", y = n, fill = class)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y") +
geom_text(aes(label = paste0(round(prop, 1), "%")),
position = position_stack(vjust = 0.5)) +
theme_void()
小结:饼图通过coord_polar()实现,但通常柱状图更有效。
误差条展示测量的不确定性。
# 计算汇总统计
df_summary <- mpg %>%
group_by(class) %>%
summarise(
mean_hwy = mean(hwy),
sd_hwy = sd(hwy),
n = n(),
se = sd_hwy / sqrt(n)
)
# 添加误差条的柱状图
ggplot(df_summary, aes(x = class, y = mean_hwy)) +
geom_col(fill = "steelblue") +
geom_errorbar(aes(ymin = mean_hwy - se, ymax = mean_hwy + se),
width = 0.2)
# 点图+误差条
ggplot(df_summary, aes(x = class, y = mean_hwy)) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = mean_hwy - se, ymax = mean_hwy + se),
width = 0.2) +
geom_linerange(aes(ymin = mean_hwy - se, ymax = mean_hwy + se),
color = "gray")
小结:geom_errorbar()和geom_linerange()用于添加误差条。
平滑曲线展示数据的趋势。
# 默认平滑(loess)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
# 线性回归
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(method = "lm")
## `geom_smooth()` using formula = 'y ~ x'
# 按组分组
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE)
## `geom_smooth()` using formula = 'y ~ x'
# 自定义平滑参数
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(method = "loess", span = 0.5, se = TRUE, level = 0.95)
## `geom_smooth()` using formula = 'y ~ x'
小结:geom_smooth()自动添加趋势线,支持多种平滑方法。
分位图展示分位数回归结果。
# 分位数回归
# 注意:geom_quantile需要quantreg包
library(quantreg)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.3) +
geom_quantile(quantiles = c(0.25, 0.5, 0.75)) +
scale_color_manual(values = c("0.25" = "red", "0.5" = "blue", "0.75" = "green"))
## Smoothing formula not specified. Using: y ~ x
## Warning: No shared levels found between `names(values)` of the manual scale and the
## data's colour values.
小结:分位数回归展示不同分位数的趋势。需要安装quantreg包。
添加文本和标签注释。
# geom_text()添加文本
ggplot(mpg[1:30, ], aes(x = displ, y = hwy)) +
geom_point() +
geom_text(aes(label = manufacturer), vjust = -0.5, size = 3)
# geom_label()添加带背景的标签
ggplot(mpg[1:20, ], aes(x = displ, y = hwy)) +
geom_point() +
geom_label(aes(label = manufacturer), vjust = -0.5, size = 3)
# annotate()添加固定文本
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
annotate("text", x = 6, y = 40, label = "高油耗车型",
color = "red", size = 5)
# 添加矩形注释
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
annotate("rect", xmin = 5, xmax = 7, ymin = 35, ymax = 45,
alpha = 0.2, fill = "red")
# 添加箭头
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
annotate("segment", x = 5, xend = 6.5, y = 35, yend = 42,
arrow = arrow(), color = "red")
小结:geom_text()映射变量,annotate()添加固定注释。
热图用颜色展示二维数据。
# 创建矩阵数据
df <- expand.grid(x = 1:5, y = 1:5)
df$value <- rnorm(25)
# geom_tile()
ggplot(df, aes(x = x, y = y, fill = value)) +
geom_tile()
# geom_raster()(更高效)
ggplot(df, aes(x = x, y = y, fill = value)) +
geom_raster()
# 相关性热图
cor_matrix <- cor(mtcars[, 1:6])
cor_df <- reshape2::melt(cor_matrix)
ggplot(cor_df, aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "blue", mid = "white", high = "red",
midpoint = 0) +
theme_minimal()
小结:geom_tile()和geom_raster()用于创建热图。
标度(Scales)控制数据值到图形属性的映射方式。本章详细介绍各种标度函数的使用方法。
颜色是最常用的图形属性之一。
# 离散变量的颜色映射
# scale_color_brewer():使用ColorBrewer调色板
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(size = 2) +
scale_color_brewer(palette = "Set1")
# 查看可用的调色板
# RColorBrewer::display.brewer.all()
# 常用调色板
# 分类调色板:Set1, Set2, Set3, Dark2, Paired等
# 序列调色板:Blues, Greens, Reds, Oranges等
# 发散调色板:RdBu, RdYlBu, Spectral等
# scale_color_hue():使用HCL色彩空间
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(size = 2) +
scale_color_hue(h = c(0, 360) + 15, l = 65, c = 100)
# scale_color_grey():灰度调色板
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(size = 2) +
scale_color_grey(start = 0.2, end = 0.8)
# 填充颜色(用于柱状图、箱线图等)
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar() +
scale_fill_brewer(palette = "Set2")
# 连续变量的颜色映射
# scale_color_gradient():双色渐变
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_gradient(low = "blue", high = "red")
# scale_color_gradient2():三色渐变(发散)
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_gradient2(low = "blue", mid = "white", high = "red",
midpoint = median(mpg$cty))
# scale_color_gradientn():多色渐变
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_gradientn(colors = c("blue", "green", "yellow", "red"))
# scale_color_viridis_c():viridis色系(色盲友好)
# 需要安装viridis包
# library(viridis)
# ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
# geom_point(size = 2) +
# scale_color_viridis_c()
# scale_color_distiller():ColorBrewer连续调色板
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_distiller(palette = "RdYlBu", direction = -1)
小结:离散变量使用scale_color_brewer(),连续变量使用scale_color_gradient()系列。
形状标度控制点的形状。
# scale_shape():离散形状标度
ggplot(mpg, aes(x = displ, y = hwy, shape = drv)) +
geom_point(size = 2) +
scale_shape()
# scale_shape_manual():手动指定形状
ggplot(mpg, aes(x = displ, y = hwy, shape = drv)) +
geom_point(size = 2) +
scale_shape_manual(values = c(16, 17, 18))
# 查看可用的形状
df_shapes <- data.frame(
shape = 0:25,
x = rep(1:13, 2),
y = rep(2:1, each = 13)
)
ggplot(df_shapes, aes(x = x, y = y, shape = shape)) +
geom_point(size = 3) +
scale_shape_identity() +
geom_text(aes(label = shape), vjust = -1, size = 3) +
theme_void()
# 形状0-20:空心形状(可填充)
# 形状21-25:实心形状(有边框和填充)
ggplot(mpg, aes(x = displ, y = hwy, shape = drv, fill = drv)) +
geom_point(size = 3) +
scale_shape_manual(values = c(21, 22, 23))
小结:R提供26种预设形状,形状21-25支持边框和填充颜色。
大小标度控制点或线条的粗细。
# scale_size():连续大小标度
ggplot(mpg, aes(x = displ, y = hwy, size = cty)) +
geom_point() +
scale_size()
# scale_size_continuous():指定范围
ggplot(mpg, aes(x = displ, y = hwy, size = cty)) +
geom_point() +
scale_size_continuous(range = c(1, 6))
# scale_size_area():面积比例(半径平方)
ggplot(mpg, aes(x = displ, y = hwy, size = cty)) +
geom_point() +
scale_size_area(max_size = 6)
# scale_size_binned():分箱大小
ggplot(mpg, aes(x = displ, y = hwy, size = cty)) +
geom_point() +
scale_size_binned(breaks = c(10, 15, 20, 25, 30))
# scale_size_manual():离散大小
# 注意:values的数量要与离散变量的水平数一致
ggplot(mpg, aes(x = displ, y = hwy, size = factor(cyl))) +
geom_point(alpha = 0.5) +
scale_size_manual(values = c(2, 3, 4, 6))
小结:scale_size()控制点的大小,range参数设置最小和最大值。使用scale_size_manual()时,values数量要与离散变量水平数一致。
线条类型标度控制线条的样式。
# scale_linetype():离散线条类型
df <- data.frame(
x = rep(1:10, 3),
y = c(1:10, 1:10 + 2, 1:10 + 4),
group = rep(c("A", "B", "C"), each = 10)
)
ggplot(df, aes(x = x, y = y, linetype = group)) +
geom_line(linewidth = 1) +
scale_linetype()
# scale_linetype_manual():手动指定
ggplot(df, aes(x = x, y = y, linetype = group)) +
geom_line(linewidth = 1) +
scale_linetype_manual(values = c("solid", "dashed", "dotted"))
# 线条类型:
# 0 = blank, 1 = solid, 2 = dashed, 3 = dotted
# 4 = dotdash, 5 = longdash, 6 = twodash
小结:R提供6种预设线条类型,可通过名称或数字指定。
透明度标度控制图形元素的透明度。
# scale_alpha():连续透明度
ggplot(mpg, aes(x = displ, y = hwy, alpha = cty)) +
geom_point(size = 3) +
scale_alpha(range = c(0.1, 1))
# scale_alpha_manual():离散透明度
ggplot(mpg, aes(x = displ, y = hwy, alpha = drv)) +
geom_point(size = 3) +
scale_alpha_manual(values = c(0.3, 0.6, 0.9))
# 直接设置透明度(不映射变量)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.3, size = 3)
小结:透明度范围0-1,值越小越透明,适合处理重叠点。
坐标轴标度控制坐标轴的范围、断点和标签。
# scale_x_continuous()和scale_y_continuous()
# 设置范围
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(limits = c(0, 10)) +
scale_y_continuous(limits = c(0, 50))
# 设置断点
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(breaks = seq(0, 8, 2)) +
scale_y_continuous(breaks = c(10, 20, 30, 40))
# 设置标签
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(breaks = 1:8, labels = paste0(1:8, "L")) +
scale_y_continuous(labels = scales::number_format(suffix = " mpg"))
# 同时设置断点和标签
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_y_continuous(
breaks = c(15, 25, 35, 45),
labels = c("低", "中", "高", "很高")
)
# 扩展坐标轴范围
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(expand = expansion(mult = 0.1)) # 扩展10%
# 次要断点
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(minor_breaks = seq(0, 8, 0.5))
# scale_x_discrete()和scale_y_discrete()
# 设置显示的类别
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
scale_x_discrete(limits = c("compact", "midsize", "suv"))
## Warning: Removed 84 rows containing missing values or values outside the scale range
## (`stat_boxplot()`).
# 重新排序类别
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
scale_x_discrete(limits = rev(unique(mpg$class)))
# 修改标签
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
scale_x_discrete(labels = toupper(unique(mpg$class)))
小结:limits控制范围,breaks控制断点,labels控制标签。
日期轴需要特殊的标度处理。
# scale_x_date():日期轴
# 创建时间序列数据
df <- data.frame(
date = seq(as.Date("2020-01-01"), as.Date("2020-12-31"), by = "month"),
value = rnorm(12, mean = 100, sd = 20)
)
# 基础日期图
ggplot(df, aes(x = date, y = value)) +
geom_line() +
geom_point()
# 设置日期断点
ggplot(df, aes(x = date, y = value)) +
geom_line() +
geom_point() +
scale_x_date(date_breaks = "2 months")
# 设置日期标签格式
ggplot(df, aes(x = date, y = value)) +
geom_line() +
geom_point() +
scale_x_date(date_breaks = "2 months", date_labels = "%Y-%m")
# 常用日期格式:
# %Y:四位年份,%y:两位年份
# %m:两位月份,%b:缩写月份,%B:完整月份
# %d:两位日期,%a:缩写星期,%A:完整星期
# 日期范围
ggplot(df, aes(x = date, y = value)) +
geom_line() +
geom_point() +
scale_x_date(limits = as.Date(c("2020-03-01", "2020-09-30")))
## Warning: Removed 5 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 5 rows containing missing values or values outside the scale range
## (`geom_point()`).
# scale_x_datetime():日期时间轴
# scale_x_time():时间轴
小结:date_breaks设置断点间隔,date_labels设置显示格式。
手动标度函数允许完全自定义映射。
# scale_*_manual():手动指定值
# 手动颜色
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point(size = 2) +
scale_color_manual(
values = c("4" = "red", "f" = "green", "r" = "blue"),
name = "驱动方式",
labels = c("四驱", "前驱", "后驱")
)
# 手动填充
ggplot(mpg, aes(x = class, fill = drv)) +
geom_bar() +
scale_fill_manual(
values = c("4" = "steelblue", "f" = "coral", "r" = "gold"),
name = "驱动方式"
)
# scale_*_identity():直接使用数据值
df <- data.frame(
x = 1:5,
y = 1:5,
color = c("red", "blue", "green", "orange", "purple")
)
ggplot(df, aes(x = x, y = y, color = color)) +
geom_point(size = 4) +
scale_color_identity()
小结:scale_*_manual()手动指定映射值,scale_*_identity()直接使用数据值。
通过标度函数实现坐标轴变换。
# 对数坐标
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_log10() +
scale_y_log10()
# 等价于
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_trans(x = "log10", y = "log10")
# sqrt变换
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_sqrt()
# 倒数变换
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_reverse()
# 使用scales包的变换
# library(scales)
# scale_x_continuous(trans = "logit") # logit变换
小结:scale_*_log10()、scale_*_sqrt()、scale_*_reverse()实现常用变换。
使用labs()函数调整图例和标题。
# labs()函数设置标题和标签
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
labs(
title = "发动机排量与油耗关系", # 主标题
subtitle = "数据来源:mpg数据集", # 副标题
caption = "图1:散点图示例", # 说明文字
x = "发动机排量 (L)", # X轴标签
y = "高速公路油耗 (mpg)", # Y轴标签
color = "车型类别" # 图例标题
)
# 单独设置
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
ggtitle("散点图标题") +
xlab("X轴") +
ylab("Y轴")
# 移除标签
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
labs(x = NULL, y = NULL, color = NULL)
# 图例位置
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
theme(legend.position = "bottom") # "top", "bottom", "left", "right", "none"
# 图例位置坐标
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
theme(legend.position = c(0.9, 0.8)) # 0-1之间的坐标
# 图例方向
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
theme(
legend.position = "bottom",
legend.direction = "vertical"
)
# 移除图例
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
guides(color = "none")
# 或者使用scale函数
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
scale_color_discrete(guide = "none")
小结:labs()设置标题和标签,theme()控制图例位置,guides()控制图例显示。
| 标度类型 | 函数 | 用途 |
|---|---|---|
| 离散颜色 | scale_color_brewer() |
ColorBrewer调色板 |
| 连续颜色 | scale_color_gradient() |
双色渐变 |
| 形状 | scale_shape_manual() |
手动指定形状 |
| 大小 | scale_size_continuous() |
连续大小映射 |
| 线条 | scale_linetype() |
线条类型 |
| 透明度 | scale_alpha() |
透明度映射 |
| 坐标轴 | scale_x/y_continuous() |
连续坐标轴 |
| 日期轴 | scale_x_date() |
日期坐标轴 |
| 手动 | scale_*_manual() |
手动指定值 |
| 变换 | scale_*_log10() |
对数变换 |
坐标系定义数据到平面的映射方式,分面将数据分割成多个子图。
笛卡尔坐标系是最常用的坐标系。
# coord_cartesian():笛卡尔坐标系(默认)
# 缩放视图(不删除数据)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_cartesian(xlim = c(2, 6), ylim = c(20, 40))
# 与limits的区别
# scale_x_continuous(limits = ...)会删除范围外的数据
# coord_cartesian(xlim = ...)只是缩放视图,不删除数据
# 示例:平滑曲线
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(method = "lm")
# 使用limits(平滑线基于可见数据)
p + scale_x_continuous(limits = c(2, 6))
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 27 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 27 rows containing missing values or values outside the scale range
## (`geom_point()`).
# 使用coord_cartesian(平滑线基于全部数据)
p + coord_cartesian(xlim = c(2, 6))
## `geom_smooth()` using formula = 'y ~ x'
小结:coord_cartesian()缩放视图但不删除数据,适合查看局部细节。
固定纵横比确保x轴和y轴单位长度相同。
# coord_fixed():固定纵横比
# 默认ratio=1(x轴和y轴单位长度相同)
ggplot(mpg, aes(x = cty, y = hwy)) +
geom_point() +
coord_fixed()
# 设置不同的比例
ggplot(mpg, aes(x = cty, y = hwy)) +
geom_point() +
coord_fixed(ratio = 0.5) # y轴单位长度是x轴的一半
# 地图示例(保持地理比例)
# ggplot(map_data, aes(x = long, y = lat)) +
# geom_path() +
# coord_fixed(ratio = 1.3)
小结:coord_fixed()适合需要保持真实比例的图形,如地图。
极坐标系将数据映射到圆形。
# coord_polar():极坐标系
# 饼图
ggplot(mpg, aes(x = factor(1), fill = class)) +
geom_bar(width = 1) +
coord_polar(theta = "y") +
theme_void()
# 玫瑰图(南丁格尔图)
ggplot(mpg, aes(x = class, fill = class)) +
geom_bar() +
coord_polar() +
theme_void()
# 雷达图
df <- data.frame(
category = rep(c("A", "B", "C", "D", "E"), 2),
value = c(3, 4, 2, 5, 4, 2, 3, 4, 3, 5),
group = rep(c("Group1", "Group2"), each = 5)
)
ggplot(df, aes(x = category, y = value, color = group, group = group)) +
geom_line() +
coord_polar()
# 设置起始角度
ggplot(mpg, aes(x = factor(1), fill = class)) +
geom_bar(width = 1) +
coord_polar(theta = "y", start = 0) # 从12点钟方向开始
小结:极坐标系用于创建饼图、玫瑰图和雷达图。
翻转坐标系交换x轴和y轴。
# coord_flip():翻转坐标系
# 水平箱线图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
coord_flip()
# 水平柱状图
ggplot(mpg, aes(x = class)) +
geom_bar() +
coord_flip()
# 注意:coord_flip()在新版本ggplot2中已弃用
# 推荐使用orientation参数
ggplot(mpg, aes(x = hwy, y = class)) +
geom_boxplot(orientation = "y")
小结:coord_flip()交换坐标轴,适合创建水平图形。
地图投影将地球表面映射到平面。
# coord_map():地图投影(需要mapproj包)
# library(mapproj)
# 世界地图
# world <- map_data("world")
# ggplot(world, aes(x = long, y = lat, group = group)) +
# geom_polygon(fill = "lightgray", color = "black") +
# coord_map(projection = "mercator")
# 不同投影
# coord_map(projection = "mercator") # 墨卡托投影
# coord_map(projection = "ortho") # 正射投影
# coord_map(projection = "gilbert") # 吉尔伯特投影
# coord_sf():使用sf包的坐标系
# library(sf)
# ggplot(sf_data) +
# geom_sf() +
# coord_sf(crs = 4326) # WGS84坐标系
小结:coord_map()和coord_sf()用于地图投影。
facet_wrap()按单个变量创建多个面板。
# facet_wrap():按单变量分面
# 基础分面
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class)
# 设置列数
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, ncol = 4)
# 设置行数
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, nrow = 3)
# 分面方向
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, dir = "v") # 垂直方向排列
# 分面标签格式
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, labeller = label_both)
# 自定义标签
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class,
labeller = labeller(class = c(
"compact" = "紧凑型",
"midsize" = "中型",
"suv" = "SUV"
)))
小结:facet_wrap()按单变量分面,可控制行列数和标签格式。
facet_grid()按两个变量创建网格分面。
# facet_grid():按双变量分面
# 行按drv,列按cyl
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl)
# 只按行分面
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ .)
# 只按列分面
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(. ~ cyl)
# 分面标签
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl,
labeller = label_both,
switch = "both") # 标签位置
小结:facet_grid()创建二维网格分面,适合展示两个变量的交叉效应。
分面可以设置各面板使用独立的标度。
# scales参数控制标度
# 各面板独立坐标轴
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, scales = "free")
# 只x轴独立
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, scales = "free_x")
# 只y轴独立
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, scales = "free_y")
# 空间比例
# 注意:facet_wrap的space参数只支持"free_x", "free_y", "fixed"
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, scales = "free", space = "free_x")
# 如果需要两个方向都自由,可以使用facet_grid
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ class, scales = "free", space = "free")
小结:scales = "free"使各面板坐标轴独立。facet_wrap()的space参数只支持”free_x”、“free_y”、“fixed”,如需双向自由空间请使用facet_grid()。
调整分面标签和面板间距。
# 分面标签位置
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, strip.position = "bottom")
# 标签文本样式
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class) +
theme(
strip.text = element_text(size = 10, face = "bold", color = "white"),
strip.background = element_rect(fill = "steelblue")
)
# 面板间距
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class) +
theme(panel.spacing = unit(1, "cm"))
# 分面边框
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class) +
theme(panel.border = element_rect(color = "gray", fill = NA))
小结:通过theme()函数调整分面标签和间距。
主题控制图形的非数据元素外观,包括背景、网格线、字体等。
ggplot2提供多种内置主题。
# 创建基础图形
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point() +
labs(title = "发动机排量与油耗关系")
# theme_gray():默认灰色主题
p + theme_gray()
# theme_bw():黑白主题
p + theme_bw()
# theme_classic():经典主题(无网格)
p + theme_classic()
# theme_minimal():极简主题
p + theme_minimal()
# theme_dark():深色主题
p + theme_dark()
# theme_light():浅色主题
p + theme_light()
# theme_void():空白主题
p + theme_void()
# theme_test():测试主题
p + theme_test()
小结:内置主题提供快速的风格切换,theme_minimal()和theme_classic()最常用。
使用theme()函数调整主题元素。
# theme()函数的基本用法
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# 调整单个元素
p + theme(
plot.title = element_text(size = 14, face = "bold")
)
# 链式调整
p +
ggtitle("标题") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5),
axis.title = element_text(size = 12)
)
# 注意:theme()的设置会覆盖theme_*()的设置
# 建议先设置主题,再调整具体元素
小结:theme()函数可以精细控制图形的各个元素。
文本元素包括标题、轴标签、刻度标签等。
# 文本元素调整
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
labs(title = "主标题", subtitle = "副标题",
x = "X轴标签", y = "Y轴标签",
caption = "说明文字")
p + theme(
# 主标题
plot.title = element_text(
size = 16, # 字体大小
face = "bold", # 字体样式:plain, bold, italic, bold.italic
color = "darkblue", # 颜色
hjust = 0.5, # 水平对齐(0-1)
vjust = 1, # 垂直对齐
angle = 0, # 旋转角度
margin = ggplot2::margin(t = 10, b = 10) # 边距
),
# 副标题
plot.subtitle = element_text(size = 12, color = "gray"),
# 说明文字
plot.caption = element_text(size = 10, hjust = 1, color = "gray"),
# 轴标题
axis.title = element_text(size = 12, face = "bold"),
axis.title.x = element_text(margin = ggplot2::margin(t = 10)),
axis.title.y = element_text(margin = ggplot2::margin(r = 10)),
# 轴刻度标签
axis.text = element_text(size = 10, color = "black"),
axis.text.x = element_text(angle = 45, hjust = 1),
# 图例文本
legend.text = element_text(size = 10),
legend.title = element_text(size = 12, face = "bold")
)
小结:文本元素使用element_text()调整,可控制大小、颜色、角度等。
矩形元素包括背景、面板等。
# 矩形元素调整
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
p + theme(
# 图形背景
plot.background = element_rect(
fill = "white", # 填充色
color = "black", # 边框色
linewidth = 1 # 边框宽度
),
# 面板背景
panel.background = element_rect(fill = "lightgray"),
# 分面背景
strip.background = element_rect(fill = "steelblue", color = NA),
# 图例背景
legend.background = element_rect(fill = "white", color = "gray"),
# 图例框
legend.box.background = element_rect(fill = "lightyellow")
)
# 移除背景
p + theme(
panel.background = element_blank(),
plot.background = element_blank()
)
小结:矩形元素使用element_rect()调整,可控制填充色和边框。
线条元素包括网格线、坐标轴线等。
# 线条元素调整
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
p + theme(
# 主网格线
panel.grid.major = element_line(color = "gray", linewidth = 0.5),
panel.grid.major.x = element_line(color = "red"),
panel.grid.major.y = element_line(color = "blue"),
# 次网格线
panel.grid.minor = element_line(color = "lightgray", linewidth = 0.25),
# 坐标轴线
axis.line = element_line(color = "black", linewidth = 1),
axis.line.x = element_line(color = "red"),
axis.line.y = element_line(color = "blue"),
# 刻度线
axis.ticks = element_line(color = "black"),
axis.ticks.x = element_line(color = "red"),
axis.ticks.y = element_line(color = "blue"),
# 分面边框
panel.border = element_rect(color = "black", fill = NA, linewidth = 1)
)
# 移除网格线
p + theme(panel.grid = element_blank())
# 只保留y轴网格线
p + theme(panel.grid.x = element_blank())
## Warning in plot_theme(plot): The `panel.grid.x` theme element is not defined in
## the element hierarchy.
小结:线条元素使用element_line()调整,可控制颜色、宽度和类型。
图例是重要的图形元素,需要精细调整。
# 图例位置
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point()
# 预设位置
p + theme(legend.position = "right") # 默认
p + theme(legend.position = "left")
p + theme(legend.position = "top")
p + theme(legend.position = "bottom")
p + theme(legend.position = "none") # 移除图例
# 坐标位置(0-1)
p + theme(legend.position = c(0.9, 0.8))
# 图例方向
p + theme(
legend.position = "bottom",
legend.direction = "vertical"
)
# 图例对齐
p + theme(
legend.position = "bottom",
legend.box = "horizontal" # 多个图例水平排列
)
# 图例标题和标签
p + theme(
legend.title = element_text(face = "bold"),
legend.text = element_text(size = 10),
legend.title.align = 0.5 # 标题居中
)
# 图例背景和边距
p + theme(
legend.background = element_rect(fill = "white", color = "gray"),
legend.margin = ggplot2::margin(t = 5, r = 5, b = 5, l = 5)
)
# 图例间距
p + theme(
legend.spacing = unit(1, "cm"),
legend.spacing.x = unit(0.5, "cm"),
legend.spacing.y = unit(0.5, "cm")
)
# 图例键大小
p + theme(
legend.key.size = unit(1, "cm"),
legend.key.width = unit(1.5, "cm"),
legend.key.height = unit(0.5, "cm")
)
# 移除图例键背景
p + theme(legend.key = element_blank())
小结:legend.position控制位置,legend.*系列参数控制样式。
调整图形各部分的间距和边距。
# plot.margin:图形边距
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
p + theme(plot.margin = ggplot2::margin(t = 20, r = 20, b = 20, l = 20))
# 使用单位
p + theme(plot.margin = unit(c(1, 1, 1, 1), "cm"))
# panel.spacing:面板间距
p + facet_wrap(~ drv) +
theme(panel.spacing = unit(1, "cm"))
# axis.title margin:轴标题边距
p + theme(
axis.title.x = element_text(margin = ggplot2::margin(t = 10)),
axis.title.y = element_text(margin = ggplot2::margin(r = 10))
)
# 完整边距示例
p + theme(
plot.margin = ggplot2::margin(20, 20, 20, 20),
plot.title = element_text(margin = ggplot2::margin(b = 10)),
axis.title.x = element_text(margin = ggplot2::margin(t = 10)),
axis.title.y = element_text(margin = ggplot2::margin(r = 10))
)
小结:margin()函数设置边距,参数顺序为上、右、下、左。
创建可复用的自定义主题。
# 定义自定义主题函数
theme_custom <- function(base_size = 11, base_family = "") {
theme_minimal(base_size = base_size, base_family = base_family) +
theme(
# 标题
plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 12, color = "gray50"),
# 轴
axis.title = element_text(size = 12, face = "bold"),
axis.text = element_text(size = 10),
axis.line = element_line(color = "gray30"),
# 网格
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray90"),
# 图例
legend.position = "bottom",
legend.title = element_text(face = "bold"),
# 背景
plot.background = element_rect(fill = "white", color = NA),
panel.background = element_rect(fill = "white", color = NA)
)
}
# 使用自定义主题
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point() +
labs(title = "自定义主题示例") +
theme_custom()
# 带参数的自定义主题
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point() +
labs(title = "大字体版本") +
theme_custom(base_size = 14)
小结:自定义主题函数可以封装常用设置,提高代码复用性。
使用扩展包提供的主题。
# ggthemes包
# library(ggthemes)
# p + theme_tufte() # Tufte风格
# p + theme_economist() # 经济学人风格
# p + theme_stata() # Stata风格
# p + theme_excel() # Excel风格
# p + theme_fivethirtyeight() # FiveThirtyEight风格
# p + theme_wsj() # 华尔街日报风格
# hrbrthemes包
# library(hrbrthemes)
# p + theme_ipsum() # 极简现代风格
# p + theme_ft_rc() # FT风格
# tvthemes包
# library(tvthemes)
# p + theme_simpsons() # 辛普森一家风格
# p + theme_rickAndMorty() # 瑞克和莫蒂风格
小结:扩展包提供丰富的主题选择,适合快速创建专业风格图形。
实际工作中常需要将多个图形组合在一起展示。本章介绍多种多图组合方法。
回顾基础绘图系统的多图方法。
# par(mfrow)和par(mfcol)
# 保存原始参数
old_par <- par(no.readonly = TRUE)
# 2x2布局
par(mfrow = c(2, 2))
plot(1:10, main = "图1")
hist(rnorm(100), main = "图2")
boxplot(rnorm(50), main = "图3")
pie(c(1, 2, 3), main = "图4")
# 恢复参数
par(old_par)
# mfrow vs mfcol
# mfrow:按行填充
# mfcol:按列填充
小结:par(mfrow)适合基础绘图系统,对ggplot2图形不适用。
gridExtra包提供灵活的多图布局。
# gridExtra::grid.arrange()
library(gridExtra)
# 创建多个ggplot2图形
p1 <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
ggtitle("散点图")
p2 <- ggplot(mpg, aes(x = class)) +
geom_bar() +
ggtitle("柱状图") +
coord_flip()
p3 <- ggplot(mpg, aes(x = hwy)) +
geom_histogram(bins = 20) +
ggtitle("直方图")
p4 <- ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
ggtitle("箱线图")
# 基础排列
grid.arrange(p1, p2, p3, p4, ncol = 2)
# 指定行数
grid.arrange(p1, p2, p3, p4, nrow = 2)
# 使用布局矩阵
layout_matrix <- matrix(c(1, 1, 2, 3, 4, 4), nrow = 2, byrow = TRUE)
grid.arrange(p1, p2, p3, p4, layout_matrix = layout_matrix)
# 指定宽高比例
grid.arrange(p1, p2, p3, p4,
widths = c(2, 1),
heights = c(1, 2))
小结:grid.arrange()可以灵活排列多个ggplot2图形。
cowplot包提供更多排版功能。
# cowplot包
library(cowplot)
# plot_grid():基础排列
plot_grid(p1, p2, p3, p4, ncol = 2)
# 添加标签
plot_grid(p1, p2, p3, p4,
ncol = 2,
labels = c("A", "B", "C", "D"),
label_size = 12)
# 自定义标签位置
plot_grid(p1, p2, p3, p4,
ncol = 2,
labels = "AUTO", # 自动生成A, B, C, D
label_x = 0.1, # 标签x位置
label_y = 0.9, # 标签y位置
hjust = 0) # 对齐方式
# 指定相对大小
plot_grid(p1, p2, p3, p4,
ncol = 2,
rel_widths = c(2, 1),
rel_heights = c(1, 2))
# 对齐图形
plot_grid(p1, p2, p3, p4,
ncol = 2,
align = "hv", # 水平和垂直对齐
axis = "tblr") # 对齐轴
# draw_plot():自由布局
ggdraw() +
draw_plot(p1, x = 0, y = 0.5, width = 0.5, height = 0.5) +
draw_plot(p2, x = 0.5, y = 0.5, width = 0.5, height = 0.5) +
draw_plot(p3, x = 0, y = 0, width = 1, height = 0.5)
# draw_label():添加标签
ggdraw() +
draw_plot(p1) +
draw_label("自定义标签", x = 0.5, y = 0.9, size = 14, color = "red")
小结:cowplot提供plot_grid()和draw_plot()两种排版方式。
patchwork包使用操作符组合图形,语法简洁。
# patchwork包
library(patchwork)
# 使用+组合图形
p1 + p2
# 使用/垂直排列
p1 / p2
# 使用|水平排列
p1 | p2
# 组合使用
(p1 | p2) / p3
# 复杂布局
p1 + p2 + p3 + p4 +
plot_layout(nrow = 2, ncol = 2)
# 指定宽高比例
p1 + p2 +
plot_layout(widths = c(2, 1))
# 嵌套布局
p1 + (p2 + p3) + p4 +
plot_layout(nrow = 1)
# 添加整体标题
p1 + p2 + p3 + p4 +
plot_annotation(
title = "整体标题",
subtitle = "副标题",
caption = "说明文字",
tag_levels = "A" # 自动添加A, B, C, D标签
)
# 自定义标签
p1 + p2 + p3 + p4 +
plot_annotation(tag_levels = list(c("图1", "图2", "图3", "图4")))
小结:patchwork使用+、|、/操作符,语法简洁直观。
在主图中插入子图。
# 使用cowplot插入子图
# 主图
main_plot <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
theme_bw()
# 子图
inset_plot <- ggplot(mpg, aes(x = hwy)) +
geom_histogram(bins = 20, fill = "steelblue") +
theme_void()
# 插入子图
ggdraw(main_plot) +
draw_plot(inset_plot, x = 0.6, y = 0.6, width = 0.35, height = 0.35)
# 使用patchwork
main_plot +
inset_element(inset_plot,
left = 0.6, right = 1,
bottom = 0.6, top = 1)
小结:cowplot的draw_plot()和patchwork的inset_element()都可以插入子图。
多个图形共用图例或坐标轴。
# 共用图例(cowplot)
# 创建带图例的图形
p1 <- ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point()
p2 <- ggplot(mpg, aes(x = cty, y = hwy, color = drv)) +
geom_point()
# 提取图例
legend <- get_legend(p1)
# 移除图例后组合
p1_no_legend <- p1 + theme(legend.position = "none")
p2_no_legend <- p2 + theme(legend.position = "none")
# 组合并添加图例
plot_grid(p1_no_legend, p2_no_legend, legend,
ncol = 3, rel_widths = c(1, 1, 0.3))
# 共用坐标轴(patchwork)
p1 + p2 +
plot_layout(ncol = 2) &
theme(plot.margin = ggplot2::margin(0, 0, 0, 0))
# 使用guide_area()(patchwork)
p1 + p2 + guide_area() +
plot_layout(guides = "collect")
小结:cowplot的get_legend()提取图例,patchwork的guides = "collect"收集图例。
使用patchwork创建复杂布局。
# plot_spacer():空白区域
p1 + plot_spacer() + p2
# area():指定区域
layout <- c(
area(1, 1, 2, 2), # 图1占据第1-2行,第1-2列
area(1, 3), # 图2占据第1行,第3列
area(2, 3), # 图3占据第2行,第3列
area(3, 1, 3, 3) # 图4占据第3行,第1-3列
)
p1 + p2 + p3 + p4 + plot_layout(design = layout)
# 使用字符串定义布局
layout <- "
##BB
AACC
####
DDEE
"
# 注意:字符串中每个字母对应一个图形
# 这里只使用p1-p4,对应A, B, C, D
p1 + p2 + p3 + p4 + plot_layout(design = layout)
# wrap_elements():包装任意图形
library(grid)
text_grob <- textGrob("自定义文本", gp = gpar(fontsize = 20))
p1 + wrap_elements(text_grob) + p2
小结:plot_spacer()、area()和字符串布局提供灵活的布局控制。
将多个图形输出到多页PDF。
# 使用pdf()设备
pdf("multipage.pdf", width = 8, height = 6)
print(p1)
print(p2)
print(p3)
dev.off()
# 使用ggsave()保存组合图形
combined <- p1 + p2 + p3 + p4
ggsave("combined.pdf", combined, width = 12, height = 8)
# 使用cowplot的save_plot()
# save_plot("combined.pdf", combined, ncol = 2, nrow = 2)
小结:pdf()设备可以输出多页PDF,ggsave()保存单个图形。
本章深入介绍颜色选择、字体设置和标注技巧,帮助创建更专业的图形。
RColorBrewer提供经过精心设计的调色板。
# RColorBrewer包
library(RColorBrewer)
# 查看所有调色板
display.brewer.all()
# 查看特定调色板的颜色
display.brewer.pal(8, "Set1")
# 获取调色板颜色
colors <- brewer.pal(8, "Set1")
colors
## [1] "#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00" "#FFFF33" "#A65628"
## [8] "#F781BF"
# 调色板类型
# 分类调色板(qualitative):Set1, Set2, Set3, Dark2, Paired, Accent等
# 序列调色板(sequential):Blues, Greens, Reds, Oranges, Purples等
# 发散调色板(diverging):RdBu, RdYlBu, Spectral, BrBG等
# 获取调色板信息
brewer.pal.info
## maxcolors category colorblind
## BrBG 11 div TRUE
## PiYG 11 div TRUE
## PRGn 11 div TRUE
## PuOr 11 div TRUE
## RdBu 11 div TRUE
## RdGy 11 div FALSE
## RdYlBu 11 div TRUE
## RdYlGn 11 div FALSE
## Spectral 11 div FALSE
## Accent 8 qual FALSE
## Dark2 8 qual TRUE
## Paired 12 qual TRUE
## Pastel1 9 qual FALSE
## Pastel2 8 qual FALSE
## Set1 9 qual FALSE
## Set2 8 qual TRUE
## Set3 12 qual FALSE
## Blues 9 seq TRUE
## BuGn 9 seq TRUE
## BuPu 9 seq TRUE
## GnBu 9 seq TRUE
## Greens 9 seq TRUE
## Greys 9 seq TRUE
## Oranges 9 seq TRUE
## OrRd 9 seq TRUE
## PuBu 9 seq TRUE
## PuBuGn 9 seq TRUE
## PuRd 9 seq TRUE
## Purples 9 seq TRUE
## RdPu 9 seq TRUE
## Reds 9 seq TRUE
## YlGn 9 seq TRUE
## YlGnBu 9 seq TRUE
## YlOrBr 9 seq TRUE
## YlOrRd 9 seq TRUE
# 在ggplot2中使用
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(size = 2) +
scale_color_brewer(palette = "Set1")
# 获取色盲友好的调色板
display.brewer.all(colorblindFriendly = TRUE)
# 色盲友好调色板:Set2, Paired, Dark2等
小结:RColorBrewer提供分类、序列、发散三类调色板,部分调色板色盲友好。
viridis色系是色盲友好的现代配色方案。
# viridis包
library(viridis)
# 查看viridis色系
viridis.map
# 在ggplot2中使用
# 连续变量
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_viridis_c() # 连续
# 离散变量
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point(size = 2) +
scale_color_viridis_d() # 离散
# 选择不同的色系
# option = "A" (magma), "B" (inferno), "C" (plasma), "D" (viridis), "E" (cividis)
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_viridis_c(option = "plasma")
# 设置方向
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_viridis_c(direction = -1) # 反转颜色顺序
小结:viridis色系色盲友好,适合连续和离散变量。
创建自定义颜色向量。
# 使用颜色名称
colors <- c("red", "blue", "green", "orange", "purple")
# 使用十六进制颜色码
colors_hex <- c("#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7")
# 使用RGB值
colors_rgb <- rgb(red = c(1, 0, 0), green = c(0, 1, 0), blue = c(0, 0, 1))
# 创建颜色调色板
my_palette <- colorRampPalette(c("blue", "white", "red"))
my_colors <- my_palette(10)
# 在ggplot2中使用
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point(size = 2) +
scale_color_manual(values = c("4" = "#FF6B6B",
"f" = "#4ECDC4",
"r" = "#45B7D1"))
# 使用颜色渐变函数
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point(size = 2) +
scale_color_gradientn(colors = c("blue", "green", "yellow", "red"))
# 从图片提取颜色(使用colorfindr包)
# library(colorfindr)
# colors <- get_colors("image.jpg") %>% make_palette()
小结:可以使用颜色名称、十六进制码或RGB值自定义颜色。
创建自定义渐变色。
# scale_fill_gradient():双色渐变
ggplot(mpg, aes(x = class, y = hwy, fill = hwy)) +
geom_col() +
scale_fill_gradient(low = "lightblue", high = "darkblue")
# scale_fill_gradient2():三色渐变(发散)
ggplot(mpg, aes(x = class, y = hwy, fill = hwy)) +
geom_col() +
scale_fill_gradient2(low = "blue", mid = "white", high = "red",
midpoint = median(mpg$hwy))
# scale_fill_gradientn():多色渐变
ggplot(mpg, aes(x = class, y = hwy, fill = hwy)) +
geom_col() +
scale_fill_gradientn(colors = c("blue", "cyan", "yellow", "red"))
# 使用colorRampPalette创建渐变
my_gradient <- colorRampPalette(c("navy", "steelblue", "lightblue"))
ggplot(mpg, aes(x = class, y = hwy, fill = hwy)) +
geom_col() +
scale_fill_gradientn(colors = my_gradient(100))
# 使用colorspace包创建感知均匀的渐变
# library(colorspace)
# scale_fill_continuous_sequential(palette = "Viridis")
小结:gradient系列函数创建渐变色,gradient2适合有中心点的数据。
设置图形中的字体。
# 查看可用字体
# Windows系统
windowsFonts()
# 基础绘图系统设置字体
par(family = "serif") # 衬线字体
par(family = "sans") # 无衬线字体
par(family = "mono") # 等宽字体
# ggplot2中设置字体
library(ggplot2)
# 方法1:在theme中设置
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
theme(text = element_text(family = "serif"))
# 方法2:使用showtext包
# library(showtext)
# showtext_auto()
# font_add("custom", "path/to/font.ttf")
# 方法3:使用extrafont包
# library(extrafont)
# font_import() # 导入系统字体
# loadfonts() # 加载字体
# fonts() # 查看可用字体
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# theme(text = element_text(family = "Arial"))
# 使用hrbrthemes包的字体主题
# library(hrbrthemes)
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# theme_ipsum() # 使用Roboto Condensed字体
小结:可以通过theme()或extrafont/showtext包设置字体。
在图形中使用系统安装的字体。
# extrafont包:使用系统字体
# library(extrafont)
# 导入字体(只需运行一次)
# font_import()
# 加载字体
# loadfonts()
# 查看可用字体
# fonts()
# 在ggplot2中使用
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# ggtitle("标题") +
# theme(
# plot.title = element_text(family = "SimHei", size = 16), # 黑体
# axis.title = element_text(family = "SimSun") # 宋体
# )
# showtext包:更灵活的字体支持
# library(showtext)
# 添加字体文件
# font_add("heiti", "C:/Windows/Fonts/simhei.ttf")
# font_add("songti", "C:/Windows/Fonts/simsun.ttc")
# 自动使用showtext
# showtext_auto()
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# theme(text = element_text(family = "heiti"))
# 中文字体常用选项
# SimHei:黑体
# SimSun:宋体
# Microsoft YaHei:微软雅黑
# KaiTi:楷体
小结:extrafont和showtext包可以在R图形中使用系统字体。
使用高级标注功能。
# annotate():添加固定注释
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
annotate("text", x = 6, y = 40, label = "高油耗区域",
color = "red", size = 5, fontface = "bold") +
annotate("rect", xmin = 5, xmax = 7, ymin = 35, ymax = 45,
alpha = 0.2, fill = "red") +
annotate("segment", x = 2, xend = 5, y = 15, yend = 20,
arrow = arrow(), color = "blue")
# ggrepel包:避免标签重叠
library(ggrepel)
# 基础文本标签(可能重叠)
ggplot(mpg[1:30, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_text()
# 使用geom_text_repel避免重叠
ggplot(mpg[1:30, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_text_repel()
# 使用geom_label_repel
ggplot(mpg[1:30, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_label_repel()
# 自定义repel参数
ggplot(mpg[1:30, ], aes(x = displ, y = hwy, label = manufacturer)) +
geom_point() +
geom_text_repel(
size = 3, # 字体大小
color = "blue", # 颜色
max.overlaps = 20, # 最大重叠数
box.padding = 0.5, # 标签间距
point.padding = 0.3, # 点与标签间距
segment.color = "gray" # 连接线颜色
)
# 只标注特定点
mpg_highlight <- mpg %>%
mutate(label = ifelse(hwy > 40, manufacturer, ""))
ggplot(mpg_highlight, aes(x = displ, y = hwy, label = label)) +
geom_point() +
geom_text_repel()
小结:annotate()添加固定注释,ggrepel包避免标签重叠。
在图形中添加数学公式。
# 使用expression()添加数学表达式
# 注意:ggplot2新版本中annotate与expression有兼容性问题,建议使用geom_text
# 创建包含数学表达式的数据框
math_df <- data.frame(
x = c(0.5, 0.5, 0.5, 0.5),
y = c(0.8, 0.6, 0.4, 0.2),
label = c("alpha + beta", "frac(1, sigma)", "sqrt(x^2 + y^2)", "integral(f(x)*dx, a, b)")
)
# 使用geom_text显示数学表达式
ggplot(math_df, aes(x = x, y = y, label = label)) +
geom_text(parse = TRUE, size = 6) +
xlim(0, 1) +
ylim(0, 1) +
labs(title = "数学表达式示例", x = "", y = "")
# 常用数学符号
# 希腊字母:alpha, beta, gamma, delta, pi, sigma, omega等
# 运算符:+、-、*、/、^、%
# 特殊符号:infinity, partial, nabla
# 分数:frac(a, b)
# 根号:sqrt(x)
# 上下标:x^2, x_i
# 求和:sum(x[i], i=1, n)
# 积分:integral(f(x)*dx, a, b)
# 在轴标签中使用(推荐方式)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
labs(
x = expression(paste("Displacement (", cm^3, ")")),
y = expression(paste("Fuel Efficiency (", km/L, ")")),
title = expression(paste(alpha, " vs ", beta))
)
# 组合文本和表达式
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(method = "lm", formula = y ~ x) +
geom_text(x = 5, y = 40, label = "R^2 == 0.60", parse = TRUE, size = 5)
# 使用substitute()动态生成表达式
r_squared <- 0.65
label_text <- substitute(paste(R^2, " = ", r), list(r = r_squared))
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
geom_text(x = 5, y = 40, label = deparse(label_text), parse = TRUE, size = 5)
小结:expression()和parse = TRUE可以在图形中添加数学公式。推荐在labs()中使用expression,在图形中使用geom_text(parse = TRUE)。
在图形中嵌入表格。
# 使用gridExtra包嵌入表格
library(gridExtra)
# 创建表格
df_table <- data.frame(
Variable = c("displ", "hwy", "cty"),
Mean = c(mean(mpg$displ), mean(mpg$hwy), mean(mpg$cty)),
SD = c(sd(mpg$displ), sd(mpg$hwy), sd(mpg$cty))
)
# 创建表格图形
table_grob <- tableGrob(df_table, rows = NULL)
# 创建散点图
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
theme_bw()
# 组合图形和表格
grid.arrange(p, table_grob, nrow = 2, heights = c(3, 1))
# 使用ggpubr包添加统计信息
# library(ggpubr)
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# stat_cor(method = "pearson", label.x = 5, label.y = 45) # 添加相关系数
# 使用ggpmisc包添加拟合公式
# library(ggpmisc)
# ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point() +
# geom_smooth(method = "lm", formula = y ~ x) +
# stat_poly_eq(formula = y ~ x,
# aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~")),
# parse = TRUE)
# 在图形下方添加表格
# library(cowplot)
# ggdraw(p) +
# draw_grob(table_grob, x = 0.1, y = 0, width = 0.8, height = 0.2)
小结:gridExtra和ggpubr包可以在图形中嵌入表格和统计信息。
交互式可视化允许用户与图形进行交互,如缩放、悬停、筛选等。
plotly是最流行的R交互可视化包。
# 安装和加载plotly
# install.packages("plotly")
library(plotly)
# 将ggplot2转换为交互式
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point()
ggplotly(p)
# 自定义tooltip
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class,
text = paste("车型:", manufacturer,
"<br>排量:", displ,
"<br>油耗:", hwy))) +
geom_point()
ggplotly(p, tooltip = "text")
# 保存交互图形
htmlwidgets::saveWidget(ggplotly(p), "interactive_plot.html")
小结:ggplotly()可以快速将ggplot2图形转换为交互式。
使用plotly原生语法创建图形。
library(plotly)
# 散点图
plot_ly(mpg, x = ~displ, y = ~hwy, color = ~class, type = "scatter", mode = "markers")
# 折线图
plot_ly(economics, x = ~date, y = ~unemploy, type = "scatter", mode = "lines")
# 柱状图
plot_ly(mpg, x = ~class, type = "histogram")
# 箱线图
plot_ly(mpg, x = ~class, y = ~hwy, type = "box")
# 热图
plot_ly(z = ~volcano, type = "heatmap")
# 3D散点图
plot_ly(mpg, x = ~displ, y = ~hwy, z = ~cty, color = ~class, type = "scatter3d")
# 使用管道操作符
mpg %>%
plot_ly(x = ~displ, y = ~hwy) %>%
add_markers(color = ~class) %>%
layout(title = "交互式散点图")
小结:plotly原生语法更灵活,可以创建各种交互图形。
定制悬停时显示的信息。
library(plotly)
# 自定义tooltip内容
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
geom_point(aes(text = paste("车型:", manufacturer,
"<br>排量:", displ,
"<br>油耗:", hwy)))
ggplotly(p, tooltip = c("text"))
# 使用plotly原生语法定制
plot_ly(mpg, x = ~displ, y = ~hwy, color = ~class,
hoverinfo = "text",
text = ~paste("车型:", manufacturer,
"<br>排量:", displ,
"<br>油耗:", hwy)) %>%
add_markers()
# 自定义tooltip样式
plot_ly(mpg, x = ~displ, y = ~hwy,
hoverinfo = "x+y",
hoverlabel = list(bgcolor = "white",
bordercolor = "black",
font = list(size = 15))) %>%
add_markers()
小结:通过tooltip和hoverinfo参数定制悬停信息。
控制图形的交互行为。
library(plotly)
# 基础交互
p <- plot_ly(mpg, x = ~displ, y = ~hwy, color = ~class) %>%
add_markers()
# 配置交互模式
p %>% config(
scrollZoom = TRUE, # 滚轮缩放
displayModeBar = TRUE, # 显示工具栏
modeBarButtonsToRemove = c("lasso2d", "select2d") # 移除特定按钮
)
# 添加选择功能
p %>% layout(
dragmode = "select", # 框选模式
selectdirection = "h" # 水平选择
)
# 添加范围滑块
plot_ly(economics, x = ~date, y = ~unemploy) %>%
add_lines() %>%
rangeslider()
# 添加时间范围选择器
plot_ly(economics, x = ~date, y = ~unemploy) %>%
add_lines() %>%
rangeslider() %>%
layout(
xaxis = list(
rangeselector = list(
buttons = list(
list(count = 3, label = "3个月", step = "month", stepmode = "backward"),
list(count = 6, label = "6个月", step = "month", stepmode = "backward"),
list(count = 1, label = "1年", step = "year", stepmode = "backward"),
list(step = "all", label = "全部")
)
)
)
)
小结:config()和layout()函数控制交互行为。
highcharter是基于Highcharts.js的R包。
# 安装和加载
# install.packages("highcharter")
library(highcharter)
# 散点图
hchart(mpg, "scatter", hcaes(x = displ, y = hwy, group = class))
# 折线图
hchart(economics, "line", hcaes(x = date, y = unemploy))
# 柱状图
hchart(mpg, "column", hcaes(x = class, y = hwy))
# 箱线图
hchart(mpg, "boxplot", hcaes(x = class, y = hwy))
# 热图
hchart(volcano)
# 主题设置
hchart(mpg, "scatter", hcaes(x = displ, y = hwy)) %>%
hc_theme_darkunica()
# 导出选项
hchart(mpg, "scatter", hcaes(x = displ, y = hwy)) %>%
hc_exporting(enabled = TRUE)
小结:highcharter提供美观的默认样式和丰富的图表类型。
echarts4r是基于Apache ECharts的R包。
# 安装和加载
# install.packages("echarts4r")
library(echarts4r)
# 散点图
mpg %>%
e_chart(x = displ) %>%
e_scatter(y = hwy, color = class)
# 折线图
economics %>%
e_chart(x = date) %>%
e_line(y = unemploy)
# 柱状图
mpg %>%
count(class) %>%
e_chart(x = class) %>%
e_bar(y = n)
# 饼图
mpg %>%
count(class) %>%
e_chart(x = class) %>%
e_pie(y = n)
# 热力图
volcano %>%
as.data.frame() %>%
e_chart() %>%
e_heatmap() %>%
e_visual_map()
# 3D散点图
mpg %>%
e_chart(displ) %>%
e_scatter_3d(hwy, cty) %>%
e_theme("dark")
小结:echarts4r语法简洁,支持丰富的图表类型和主题。
ggiraph为ggplot2添加交互功能。
# 安装和加载
# install.packages("ggiraph")
library(ggiraph)
# 创建交互式散点图
p <- ggplot(mpg, aes(x = displ, y = hwy, color = class,
tooltip = manufacturer,
data_id = manufacturer)) +
geom_point_interactive()
girafe(ggobj = p)
# 交互式柱状图
p <- ggplot(mpg, aes(x = class, fill = drv,
tooltip = class,
data_id = class)) +
geom_bar_interactive()
girafe(ggobj = p)
# 添加悬停效果
girafe(ggobj = p,
options = list(
opts_hover(css = "fill:orange;stroke:black;")
))
小结:ggiraph为ggplot2图形添加tooltip和悬停效果。
在shiny应用中集成可视化。
# shiny与plotly集成示例
# library(shiny)
# library(plotly)
# ui <- fluidPage(
# selectInput("variable", "选择变量:",
# choices = c("hwy", "cty", "displ")),
# plotlyOutput("plot")
# )
#
# server <- function(input, output) {
# output$plot <- renderPlotly({
# p <- ggplot(mpg, aes_string(x = "displ", y = input$variable)) +
# geom_point(aes(color = class))
# ggplotly(p)
# })
# }
#
# shinyApp(ui, server)
# shiny与echarts4r集成
# library(echarts4r)
#
# ui <- fluidPage(
# echarts4rOutput("chart")
# )
#
# server <- function(input, output) {
# output$chart <- renderEcharts4r({
# mpg %>%
# e_chart(displ) %>%
# e_scatter(hwy)
# })
# }
#
# shinyApp(ui, server)
小结:plotly和echarts4r都可以与shiny无缝集成。
使用dygraphs创建交互式时间序列。
# 安装和加载
# install.packages("dygraphs")
library(dygraphs)
# 创建时间序列对象
ts_data <- ts(economics$unemploy, start = c(1967, 7), frequency = 12)
# 基础交互式时间序列
dygraph(ts_data)
# 添加范围选择器
dygraph(ts_data) %>%
dyRangeSelector()
# 添加滚动条
dygraph(ts_data) %>%
dyRangeSelector() %>%
dyRoller()
# 多系列时间序列
lungDeaths <- cbind(mdeaths, fdeaths)
dygraph(lungDeaths) %>%
dySeries("mdeaths", label = "男性") %>%
dySeries("fdeaths", label = "女性") %>%
dyLegend(show = "always")
# 添加事件标注
dygraph(ts_data) %>%
dyEvent("1980-1-1", "事件标注", labelLoc = "bottom")
# 添加阴影区域
dygraph(ts_data) %>%
dyShading(from = "1980-1-1", to = "1985-1-1")
小结:dygraphs专门用于交互式时间序列可视化。
创建交互式网络图。
# visNetwork包
# install.packages("visNetwork")
# library(visNetwork)
# 创建节点和边数据
# nodes <- data.frame(id = 1:5, label = paste("节点", 1:5))
# edges <- data.frame(from = c(1, 2, 2, 3, 4), to = c(2, 3, 4, 5, 5))
#
# visNetwork(nodes, edges)
# networkD3包
# install.packages("networkD3")
# library(networkD3)
# 创建力导向图
# simpleNetwork(edges)
# 创建桑基图
# sankeyNetwork(Links = edges, Nodes = nodes,
# Source = "from", Target = "to",
# NodeID = "label", Value = "value")
小结:visNetwork和networkD3可以创建交互式网络图。
本章介绍一些高级和专用的图表类型。
展示数据分布的高级图形。
# 密度曲线+直方图组合
ggplot(mpg, aes(x = hwy)) +
geom_histogram(aes(y = after_stat(density)), bins = 20,
fill = "steelblue", alpha = 0.5) +
geom_density(color = "red", linewidth = 1) +
theme_minimal()
# 边际分布图(使用ggExtra包)
# library(ggExtra)
# p <- ggplot(mpg, aes(x = displ, y = hwy)) +
# geom_point()
#
# ggMarginal(p, type = "histogram") # 边际直方图
# ggMarginal(p, type = "density") # 边际密度图
# ggMarginal(p, type = "boxplot") # 边际箱线图
# 分组边际图
# p <- ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
# geom_point()
#
# ggMarginal(p, type = "density", groupColour = TRUE, groupFill = TRUE)
小结:边际分布图可以同时展示双变量关系和单变量分布。
展示二维数据的密度分布。
# geom_bin2d():矩形分箱
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_bin2d(bins = 20) +
scale_fill_viridis_b()
# stat_density2d():二维密度估计
ggplot(mpg, aes(x = displ, y = hwy)) +
stat_density2d()
# 等高线图
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.3) +
stat_density2d(color = "red")
# 填充等高线
ggplot(mpg, aes(x = displ, y = hwy)) +
stat_density2d(aes(fill = after_stat(level)), geom = "polygon") +
scale_fill_viridis_c()
# 热力密度图
ggplot(mpg, aes(x = displ, y = hwy)) +
stat_density2d(aes(fill = after_stat(density)), geom = "raster", contour = FALSE) +
scale_fill_viridis_c()
小结:二维密度图适合展示大数据集的分布模式。
使用六边形分箱展示二维数据。
# geom_hex():六边形分箱
# 需要安装hexbin包
# install.packages("hexbin")
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_hex(bins = 20) +
scale_fill_viridis_c()
## Warning: Computation failed in `stat_binhex()`.
## Caused by error in `compute_group()`:
## ! The package "hexbin" is required for `stat_bin_hex()`.
# 自定义颜色
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_hex(bins = 30) +
scale_fill_gradient(low = "lightblue", high = "darkblue")
## Warning: Computation failed in `stat_binhex()`.
## Caused by error in `compute_group()`:
## ! The package "hexbin" is required for `stat_bin_hex()`.
# 大数据集示例
# ggplot(diamonds, aes(x = carat, y = price)) +
# geom_hex(bins = 50) +
# scale_fill_viridis_c()
小结:六边形分箱比矩形分箱更美观,适合大数据集。
展示集合关系。
# VennDiagram包
# install.packages("VennDiagram")
# library(VennDiagram)
# 二元韦恩图
# venn.diagram(
# x = list(A = 1:10, B = 5:15),
# filename = "venn2.png"
# )
# 三元韦恩图
# venn.diagram(
# x = list(A = 1:10, B = 5:15, C = 10:20),
# filename = "venn3.png"
# )
# eulerr包(更美观)
# install.packages("eulerr")
# library(eulerr)
# euler()函数创建欧拉图
# fit <- euler(c(A = 10, B = 15, "A&B" = 5))
# plot(fit)
# 使用ggplot2风格
# library(ggforce)
# ggplot() +
# geom_circle(aes(x0 = 0, y0 = 0, r = 1))
小结:VennDiagram和eulerr包可以创建韦恩图和欧拉图。
创建词云可视化。
# wordcloud包
# install.packages("wordcloud")
# library(wordcloud)
# 创建词频数据
# words <- c("R", "Python", "数据", "分析", "可视化", "统计", "机器学习", "深度学习")
# freq <- c(50, 40, 35, 30, 28, 25, 20, 15)
# 基础词云
# wordcloud(words, freq)
# 自定义颜色
# wordcloud(words, freq, colors = brewer.pal(8, "Dark2"))
# wordcloud2包(交互式)
# install.packages("wordcloud2")
# library(wordcloud2)
# data <- data.frame(word = words, freq = freq)
# wordcloud2(data)
# 自定义形状
# wordcloud2(data, shape = "star")
# wordcloud2(data, shape = "diamond")
小结:wordcloud创建静态词云,wordcloud2创建交互式词云。
展示多变量数据。
# fmsb包
# install.packages("fmsb")
# library(fmsb)
# 创建数据框(需要包含最大值和最小值行)
# data <- data.frame(
# rbind(
# c(5, 5, 5, 5, 5), # 最大值
# c(0, 0, 0, 0, 0), # 最小值
# c(3, 4, 2, 5, 4), # 数据1
# c(2, 3, 4, 3, 5) # 数据2
# )
# )
# colnames(data) <- c("变量1", "变量2", "变量3", "变量4", "变量5")
# rownames(data) <- c("max", "min", "组A", "组B")
# radarchart(data)
# ggradar包(ggplot2风格)
# install.packages("ggradar")
# library(ggradar)
# data <- data.frame(
# group = c("A", "B"),
# var1 = c(3, 2),
# var2 = c(4, 3),
# var3 = c(2, 4),
# var4 = c(5, 3),
# var5 = c(4, 5)
# )
#
# ggradar(data)
小结:fmsb和ggradar包可以创建雷达图。
展示多变量关系。
# GGally包
# install.packages("GGally")
# library(GGally)
# 平行坐标图
# ggparcoord(mpg, columns = c(3, 4, 5, 8, 9))
# 按组着色
# ggparcoord(mpg, columns = c(3, 4, 5, 8, 9), groupColumn = "class")
# 显示阴影
# ggparcoord(mpg, columns = c(3, 4, 5, 8, 9),
# alphaLines = 0.3,
# scale = "globalminmax")
小结:平行坐标图适合展示高维数据。
展示累计变化。
# waterfalls包
# install.packages("waterfalls")
# library(waterfalls)
# 创建数据
# data <- data.frame(
# category = c("起始", "收入A", "收入B", "支出A", "支出B", "结余"),
# value = c(100, 50, 30, -40, -20, 0)
# )
# 瀑布图
# waterfall(data)
# 使用ggplot2手动创建
# library(dplyr)
#
# data <- data.frame(
# category = c("起始", "收入A", "收入B", "支出A", "支出B"),
# value = c(100, 50, 30, -40, -20)
# ) %>%
# mutate(
# end = cumsum(value),
# start = lag(end, default = 0),
# sign = ifelse(value >= 0, "正", "负")
# )
#
# ggplot(data, aes(x = category, fill = sign)) +
# geom_rect(aes(xmin = category, xmax = category,
# ymin = start, ymax = end))
小结:瀑布图展示数值的累计变化过程。
可视化相关系数矩阵。
# corrplot包
# install.packages("corrplot")
# library(corrplot)
# 计算相关系数
# cor_matrix <- cor(mtcars)
# 基础相关图
# corrplot(cor_matrix)
# 添加数值
# corrplot(cor_matrix, method = "number")
# 圆形方法
# corrplot(cor_matrix, method = "circle")
# 组合方法
# corrplot(cor_matrix, method = "circle", type = "upper")
# corrplot(cor_matrix, method = "number", type = "lower", add = TRUE)
# ggcorrplot包(ggplot2风格)
# install.packages("ggcorrplot")
# library(gcorrplot)
# ggcorrplot(cor_matrix)
# ggcorrplot(cor_matrix, method = "circle")
# ggcorrplot(cor_matrix, hc.order = TRUE) # 聚类排序
小结:corrplot和ggcorrplot可以可视化相关系数矩阵。
创建带聚类的热图。
# pheatmap包
# install.packages("pheatmap")
# library(pheatmap)
# 创建数据矩阵
# data_matrix <- as.matrix(mtcars)
# 基础热图
# pheatmap(data_matrix)
# 标准化
# pheatmap(data_matrix, scale = "column")
# 自定义颜色
# pheatmap(data_matrix, scale = "column",
# color = colorRampPalette(c("navy", "white", "firebrick3"))(100))
# ComplexHeatmap包(更强大)
# install.packages("ComplexHeatmap")
# library(ComplexHeatmap)
# Heatmap(data_matrix)
小结:pheatmap和ComplexHeatmap可以创建带聚类的热图。
可视化层次聚类结果。
# ggdendro包
# install.packages("ggdendro")
# library(ggdendro)
# 层次聚类
# hc <- hclust(dist(mtcars))
# 基础树状图
# plot(hc)
# ggplot2风格树状图
# ggdendrogram(hc)
# factoextra包
# install.packages("factoextra")
# library(factoextra)
# fviz_dend(hc, k = 4, cex = 0.5) # 分成4类
小结:ggdendro和factoextra可以创建美观的树状图。
展示时间序列的分解结果。
# feasts包
# install.packages("feasts")
# library(feasts)
# library(fable)
# 创建tsibble对象
# ts_data <- as_tsibble(AirPassengers)
# 时间序列分解
# ts_data %>%
# model(STL(value ~ season(window = 7))) %>%
# components() %>%
# autoplot()
# 使用forecast包
# library(forecast)
# 分解
# decomp <- stl(AirPassengers, s.window = "periodic")
# autoplot(decomp)
小结:feasts和forecast包可以创建时间序列分解图。
展示生存分析结果。
# survminer包
# install.packages("survminer")
# library(survminer)
# library(survival)
# 创建生存对象
# fit <- survfit(Surv(time, status) ~ sex, data = lung)
# 基础生存曲线
# ggsurvplot(fit)
# 添加风险表
# ggsurvplot(fit, risk.table = TRUE)
# 添加置信区间
# ggsurvplot(fit, conf.int = TRUE, pval = TRUE)
小结:survminer包可以创建专业的生存曲线图。
展示效应量和置信区间。
# forestplot包
# install.packages("forestplot")
# library(forestplot)
# 创建数据
# data <- data.frame(
# name = c("研究1", "研究2", "研究3", "汇总"),
# mean = c(0.5, 0.7, 0.3, 0.5),
# lower = c(0.2, 0.4, 0.1, 0.3),
# upper = c(0.8, 1.0, 0.5, 0.7)
# )
# 森林图
# forestplot(data)
# 使用ggplot2手动创建
# ggplot(data, aes(x = mean, y = name)) +
# geom_point() +
# geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0.2) +
# geom_vline(xintercept = 0, linetype = "dashed") +
# theme_minimal()
小结:forestplot包或ggplot2可以创建森林图。
本章介绍如何创建动画可视化,使数据展示更加生动。
gganimate是ggplot2的动画扩展。
# 安装和加载
# install.packages("gganimate")
library(gganimate)
# 基础动画示例
library(gapminder)
p <- ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop, color = continent)) +
geom_point() +
scale_x_log10() +
theme_minimal()
# 添加动画
p + transition_time(year)
# 添加标题显示年份
p +
transition_time(year) +
labs(title = "Year: {frame_time}")
小结:transition_time()按时间变量创建动画。
不同的过渡方式。
library(gganimate)
# transition_time():时间过渡
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
labs(title = "Year: {frame_time}")
# transition_states():状态过渡
ggplot(mtcars, aes(x = mpg, y = disp)) +
geom_point() +
transition_states(cyl, transition_length = 1, state_length = 2) +
labs(title = "Cylinders: {closest_state}")
# transition_reveal():沿轴揭示
ggplot(economics, aes(x = date, y = unemploy)) +
geom_line() +
transition_reveal(date)
# transition_layers():逐层显示
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(aes(color = class), show.legend = FALSE) +
transition_layers(layer_length = 1, from_blank = FALSE)
小结:不同过渡函数适用于不同类型的动画。
控制元素的出现和消失。
library(gganimate)
# 进入和退出效果
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
enter_fade() + # 淡入
exit_fade() # 淡出
# 其他进入效果
# enter_appear():直接出现
# enter_grow():从小变大
# enter_recolor():颜色变化
# enter_fly():飞入
# enter_drift():漂移进入
# 其他退出效果
# exit_disappear():直接消失
# exit_shrink():变小消失
# exit_recolor():颜色变化
# exit_fly():飞出
# exit_drift():漂移退出
# 组合效果
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
enter_fade() +
enter_grow() +
exit_shrink() +
exit_fade()
小结:enter_*()和exit_*()函数控制元素的出现和消失效果。
添加阴影和轨迹效果。
library(gganimate)
# shadow_wake():尾迹效果
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
shadow_wake(wake_length = 0.1, alpha = 0.5)
# shadow_trail():轨迹点
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
shadow_trail(max_frames = 10, alpha = 0.3)
# shadow_mark():保留历史标记
ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year) +
shadow_mark(alpha = 0.3, size = 0.5)
小结:阴影效果可以展示数据的历史轨迹。
保存动画为GIF或视频。
library(gganimate)
# 创建动画
anim <- ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, size = pop)) +
geom_point() +
scale_x_log10() +
transition_time(year)
# 保存为GIF
anim_save("animation.gif", animation = anim)
# 保存为MP4视频
anim_save("animation.mp4", animation = anim)
# 自定义参数
anim_save(
"animation.gif",
animation = anim,
nframes = 100, # 帧数
fps = 10, # 每秒帧数
width = 800, # 宽度
height = 600 # 高度
)
# 使用gifski渲染器
anim_save("animation.gif", animation = anim, renderer = gifski_renderer())
# 使用av渲染器(视频)
anim_save("animation.mp4", animation = anim, renderer = av_renderer())
小结:anim_save()保存动画,支持GIF和视频格式。
在动画帧之间进行平滑插值。
# 安装和加载
# install.packages("tweenr")
library(tweenr)
# 创建两个数据状态
state1 <- data.frame(
x = 1:10,
y = rnorm(10),
group = rep(1:2, 5)
)
state2 <- data.frame(
x = 1:10,
y = rnorm(10, 2),
group = rep(1:2, 5)
)
# 插值
tweened <- tween_state(state1, state2, ease = "linear", nframes = 20)
# 在gganimate中使用
# tweenr会自动处理插值
小结:tweenr可以在数据状态之间进行平滑过渡。
在形状之间进行变换。
# 安装和加载
# install.packages("transformr")
library(transformr)
# transformr扩展了gganimate的变换能力
# 支持多边形、路径等几何对象的变换
# 示例:形状变换动画
# library(gganimate)
#
# shape1 <- data.frame(
# x = c(0, 1, 1, 0),
# y = c(0, 0, 1, 1),
# id = 1
# )
#
# shape2 <- data.frame(
# x = c(0, 0.5, 1, 0.5),
# y = c(0, 1, 0, -0.5),
# id = 2
# )
#
# shapes <- rbind(shape1, shape2)
#
# ggplot(shapes, aes(x = x, y = y, group = id)) +
# geom_polygon() +
# transition_states(id)
小结:transformr支持复杂形状之间的平滑变换。
创建时间序列的滚动动画。
library(gganimate)
# 滚动窗口动画
ggplot(economics, aes(x = date, y = unemploy)) +
geom_line() +
geom_point() +
transition_reveal(date) +
coord_cartesian(clip = "off")
# 带尾迹的时间序列
ggplot(economics, aes(x = date, y = unemploy)) +
geom_line() +
transition_reveal(date) +
shadow_trail(max_frames = 50)
# 多变量时间序列动画
economics_long <- economics %>%
pivot_longer(cols = c(pce, pop, psavert),
names_to = "variable",
values_to = "value")
ggplot(economics_long, aes(x = date, y = value, color = variable)) +
geom_line() +
facet_wrap(~variable, scales = "free_y") +
transition_reveal(date)
小结:transition_reveal()适合创建时间序列滚动动画。
创建地图动画。
library(gganimate)
# 美国州级数据动画示例
# library(maps)
#
# states <- map_data("state")
#
# # 创建时间序列数据
# states$time <- rep(1:10, each = nrow(states) / 10)
# states$value <- runif(nrow(states))
#
# ggplot(states, aes(x = long, y = lat, group = group, fill = value)) +
# geom_polygon() +
# transition_time(time) +
# coord_map()
# 使用gapminder数据
# library(gapminder)
# library(sf)
#
# # 需要地图数据
# # 创建国家数据动画
# ggplot(country_data) +
# geom_sf(aes(fill = lifeExp)) +
# transition_time(year)
小结:地图动画可以展示空间数据随时间的变化。
本章介绍如何在R中创建地图可视化。
了解常用的空间数据格式。
# sf包:简单特征
# install.packages("sf")
library(sf)
# 读取shapefile
# shapefile <- st_read("path/to/file.shp")
# 读取GeoJSON
# geojson <- st_read("path/to/file.geojson")
# 创建简单特征对象
point <- st_point(c(1, 2))
line <- st_linestring(matrix(c(0, 0, 1, 1, 2, 0), ncol = 2, byrow = TRUE))
polygon <- st_polygon(list(matrix(c(0, 0, 1, 0, 1, 1, 0, 1, 0, 0), ncol = 2, byrow = TRUE)))
# sp包(旧格式)
# library(sp)
# SpatialPoints, SpatialLines, SpatialPolygons
# 查看坐标系
# st_crs(sf_object)
# 设置坐标系
# st_set_crs(sf_object, 4326) # WGS84
# 转换坐标系
# st_transform(sf_object, 3857) # Web Mercator
小结:sf包是现代R空间数据处理的标准。
使用geom_sf绘制地图。
library(ggplot2)
library(sf)
# 使用内置数据
library(maps)
# 获取世界地图数据
world <- map_data("world")
# 基础世界地图
ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "lightgray", color = "black") +
coord_fixed(1.3)
# 使用sf对象
# ggplot(sf_object) +
# geom_sf()
# 添加坐标轴标签
ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "lightgray", color = "black") +
coord_fixed(1.3) +
labs(x = "经度", y = "纬度")
# 美国地图
usa <- map_data("usa")
ggplot(usa, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "steelblue", color = "white") +
coord_fixed(1.3)
小结:geom_polygon()和geom_sf()都可以绘制地图。
获取外部地图数据。
# rnaturalearth包:自然地球数据
# install.packages("rnaturalearth")
# install.packages("rnaturalearthdata")
library(rnaturalearth)
# 获取国家边界
# countries <- ne_countries(scale = 110, returnclass = "sf")
# 获取河流
# rivers <- ne_rivers(scale = 110, returnclass = "sf")
# 获取湖泊
# lakes <- ne_lakes(scale = 110, returnclass = "sf")
# ggplot() +
# geom_sf(data = countries) +
# geom_sf(data = rivers, color = "blue") +
# theme_minimal()
# ggmap包:从Google Maps获取地图
# install.packages("ggmap")
# library(ggmap)
# 需要API密钥
# register_google(key = "your_api_key")
# map <- get_map("New York", zoom = 10)
# ggmap(map)
# maps包:内置地图数据
library(maps)
# 世界地图
world_map <- map_data("world")
# 美国州地图
us_states <- map_data("state")
# 中国地图(需要额外数据)
# china <- map_data("china")
小结:rnaturalearth和maps包提供常用地图数据。
在地图上添加不同类型的图层。
library(ggplot2)
library(maps)
# 基础地图
world <- map_data("world")
# 添加点(城市位置)
cities <- data.frame(
city = c("New York", "London", "Tokyo", "Sydney"),
lon = c(-74, 0, 140, 151),
lat = c(41, 51, 36, -34)
)
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "lightgray", color = "white") +
geom_point(data = cities, aes(x = lon, y = lat),
color = "red", size = 3) +
coord_fixed(1.3)
# 添加线(航线)
routes <- data.frame(
from_lon = c(-74, 0, 140),
from_lat = c(41, 51, 36),
to_lon = c(0, 140, 151),
to_lat = c(51, 36, -34)
)
# 添加多边形(区域)
regions <- data.frame(
lon = c(-120, -80, -80, -120),
lat = c(30, 30, 50, 50)
)
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "lightgray", color = "white") +
geom_polygon(data = regions, aes(x = lon, y = lat),
fill = "red", alpha = 0.3) +
coord_fixed(1.3)
小结:可以在地图上叠加点、线、面等几何对象。
设置地图投影。
library(ggplot2)
library(maps)
world <- map_data("world")
# 默认投影(等距圆柱投影)
ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "lightgray", color = "white") +
coord_fixed(1.3)
# 使用coord_sf设置投影
# library(sf)
#
# world_sf <- st_as_sf(world, coords = c("long", "lat"), crs = 4326)
#
# ggplot(world_sf) +
# geom_sf() +
# coord_sf(crs = st_crs(3857)) # Web Mercator
# 常用投影代码
# 4326: WGS84(经纬度)
# 3857: Web Mercator
# 2163: US National Atlas Equal Area
# 使用mapproj包
# install.packages("mapproj")
# library(mapproj)
# ggplot(world, aes(x = long, y = lat, group = group)) +
# geom_polygon(fill = "lightgray", color = "white") +
# coord_map(projection = "mercator")
小结:coord_sf()和coord_map()可以设置地图投影。
创建分级统计地图。
library(ggplot2)
library(maps)
# 美国州级数据
us_states <- map_data("state")
# 创建模拟数据
set.seed(123)
state_data <- data.frame(
region = tolower(state.name),
value = runif(50, 0, 100)
)
# 合并数据
us_data <- merge(us_states, state_data, by = "region", all.x = TRUE)
# 分级统计图
ggplot(us_data, aes(x = long, y = lat, group = group, fill = value)) +
geom_polygon(color = "white") +
coord_fixed(1.3) +
scale_fill_viridis_c() +
theme_minimal() +
labs(fill = "数值")
# 使用离散分类
us_data$category <- cut(us_data$value,
breaks = c(0, 25, 50, 75, 100),
labels = c("低", "中低", "中高", "高"))
ggplot(us_data, aes(x = long, y = lat, group = group, fill = category)) +
geom_polygon(color = "white") +
coord_fixed(1.3) +
scale_fill_brewer(palette = "RdYlBu") +
theme_minimal()
小结:分级统计图用颜色深浅表示数值大小。
在地图上展示数据分布。
library(ggplot2)
library(maps)
world <- map_data("world")
# 创建点数据
set.seed(123)
points <- data.frame(
lon = runif(100, -180, 180),
lat = runif(100, -60, 80),
value = rnorm(100, 50, 20)
)
# 基础地图+散点
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "lightgray", color = "white") +
geom_point(data = points, aes(x = lon, y = lat, color = value, size = value),
alpha = 0.7) +
scale_color_viridis_c() +
coord_fixed(1.3) +
theme_minimal()
# 气泡地图
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "gray90", color = "white") +
geom_point(data = points, aes(x = lon, y = lat, size = value),
color = "red", alpha = 0.5) +
scale_size_continuous(range = c(1, 10)) +
coord_fixed(1.3) +
theme_void()
小结:散点图与地图结合可以展示地理分布数据。
创建热力地图。
library(ggplot2)
library(maps)
world <- map_data("world")
# 创建密集点数据
set.seed(123)
heat_points <- data.frame(
lon = rnorm(1000, 0, 50),
lat = rnorm(1000, 30, 20)
)
# 使用二维密度
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "white", color = "gray") +
stat_density2d(data = heat_points,
aes(x = lon, y = lat, fill = after_stat(level)),
geom = "polygon", alpha = 0.5) +
scale_fill_viridis_c() +
coord_fixed(1.3) +
theme_minimal()
# 使用分箱
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "white", color = "gray") +
geom_bin2d(data = heat_points, aes(x = lon, y = lat), bins = 50) +
scale_fill_viridis_c() +
coord_fixed(1.3)
小结:热力地图展示数据点的密度分布。
创建交互式地图。
# 安装和加载
# install.packages("leaflet")
library(leaflet)
# 基础地图
leaflet() %>%
addTiles() %>%
setView(lng = 0, lat = 30, zoom = 3)
# 添加标记
leaflet() %>%
addTiles() %>%
addMarkers(lng = c(-74, 0, 140), lat = c(41, 51, 36),
popup = c("New York", "London", "Tokyo"))
# 添加圆形标记
leaflet() %>%
addTiles() %>%
addCircleMarkers(lng = c(-74, 0, 140), lat = c(41, 51, 36),
radius = 10, color = "red", fillOpacity = 0.5)
# 添加多边形
leaflet() %>%
addTiles() %>%
addPolygons(lng = c(-74, -73, -73, -74), lat = c(41, 41, 40, 40),
fillColor = "red", fillOpacity = 0.5)
# 使用不同的底图
leaflet() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
setView(lng = 0, lat = 30, zoom = 3)
# 添加图例
leaflet() %>%
addTiles() %>%
addCircleMarkers(lng = c(-74, 0, 140), lat = c(41, 51, 36),
radius = c(5, 10, 15), color = c("red", "blue", "green")) %>%
addLegend(position = "bottomright",
colors = c("red", "blue", "green"),
labels = c("A", "B", "C"))
小结:leaflet创建交互式Web地图。
使用瓦片地图服务。
# ggmap包
# install.packages("ggmap")
# library(ggmap)
# 需要API密钥
# register_google(key = "your_api_key")
# 获取地图
# map <- get_map("New York", zoom = 10, source = "google")
# ggmap(map)
# 使用OpenStreetMap
# map <- get_map("New York", zoom = 10, source = "osm")
# ggmap(map)
# rosm包
# install.packages("rosm")
# library(rosm)
# 预览瓦片
# osm.plot(c(-74.1, -73.9, 40.7, 40.8))
小结:ggmap和rosm可以获取在线瓦片地图。
添加地图元素。
library(ggplot2)
library(maps)
world <- map_data("world")
# 添加比例尺
# library(ggsn)
#
# ggplot(world, aes(x = long, y = lat, group = group)) +
# geom_polygon(fill = "lightgray", color = "white") +
# coord_fixed(1.3) +
# scalebar(dist = 1000, dist_unit = "km", transform = TRUE,
# model = "WGS84")
# 添加指北针
# library(ggspatial)
#
# ggplot(world, aes(x = long, y = lat, group = group)) +
# geom_polygon(fill = "lightgray", color = "white") +
# coord_fixed(1.3) +
# annotation_north_arrow(location = "tl")
# 添加文本标注
cities <- data.frame(
city = c("New York", "London"),
lon = c(-74, 0),
lat = c(41, 51)
)
ggplot() +
geom_polygon(data = world, aes(x = long, y = lat, group = group),
fill = "lightgray", color = "white") +
geom_point(data = cities, aes(x = lon, y = lat), color = "red") +
geom_text(data = cities, aes(x = lon, y = lat, label = city),
vjust = -1, size = 3) +
coord_fixed(1.3)
小结:ggsn和ggspatial包可以添加比例尺和指北针。
本章介绍网络图和层次结构数据的可视化方法。
创建网络数据对象。
# igraph包已在setup中加载
# 从边列表创建网络
edges <- data.frame(
from = c("A", "A", "B", "B", "C", "C", "D"),
to = c("B", "C", "C", "D", "D", "E", "E")
)
g <- graph_from_data_frame(edges, directed = FALSE)
# 从邻接矩阵创建
adj_matrix <- matrix(c(
0, 1, 1, 0, 0,
1, 0, 1, 1, 0,
1, 1, 0, 1, 1,
0, 1, 1, 0, 1,
0, 0, 1, 1, 0
), nrow = 5)
g <- graph_from_adjacency_matrix(adj_matrix, mode = "undirected")
# 查看网络信息
print(g)
## IGRAPH f3af620 U--- 5 7 --
## + edges from f3af620:
## [1] 1--2 1--3 2--3 2--4 3--4 3--5 4--5
V(g) # 节点
## + 5/5 vertices, from f3af620:
## [1] 1 2 3 4 5
E(g) # 边
## + 7/7 edges from f3af620:
## [1] 1--2 1--3 2--3 2--4 3--4 3--5 4--5
# 添加节点属性
V(g)$name <- c("A", "B", "C", "D", "E")
V(g)$size <- c(10, 15, 20, 15, 10)
V(g)$color <- c("red", "blue", "green", "blue", "red")
# 添加边属性
E(g)$weight <- c(1, 2, 1, 3, 2, 1, 2)
小结:igraph是R中最常用的网络分析包。
使用igraph绘制网络图。
# 创建网络
g <- make_ring(10)
# 基础绘图
plot(g)
# 自定义样式
plot(g,
vertex.size = 20,
vertex.color = "steelblue",
vertex.label = NA,
edge.color = "gray",
edge.width = 2)
# 带标签的网络
g <- make_star(10)
V(g)$name <- LETTERS[1:10]
plot(g,
vertex.size = 25,
vertex.color = "lightblue",
vertex.label.color = "black",
vertex.label.cex = 0.8)
# 有向图
g <- make_tree(10, children = 2)
plot(g, edge.arrow.size = 0.5)
# 设置布局
plot(g, layout = layout_in_circle)
plot(g, layout = layout_with_fr)
plot(g, layout = layout_as_tree)
小结:igraph的plot()函数可以快速绘制网络图。
使用ggplot2语法绘制网络图。
# ggraph包已在setup中加载
# 创建网络
g <- make_ring(10)
# 基础ggraph
ggraph(g, layout = "fr") +
geom_edge_link() +
geom_node_point() +
theme_graph()
# 自定义样式
V(g)$name <- LETTERS[1:10]
E(g)$weight <- runif(ecount(g), 1, 5)
ggraph(g, layout = "fr") +
geom_edge_link(aes(width = weight), alpha = 0.5) +
geom_node_point(aes(color = name), size = 5) +
geom_node_text(aes(label = name), repel = TRUE) +
scale_edge_width(range = c(0.5, 2)) +
scale_color_brewer(palette = "Set1") +
theme_graph()
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set1 is 9
## Returning the palette you asked for with that many colors
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 边的样式
ggraph(g, layout = "circle") +
geom_edge_arc(aes(width = weight), strength = 0.5) +
geom_node_point(size = 5) +
theme_graph()
## Warning: The `trans` argument of `continuous_scale()` is deprecated as of ggplot2 3.5.0.
## ℹ Please use the `transform` argument instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 有向边
g <- make_tree(10, children = 2)
ggraph(g, layout = "dendrogram") +
geom_edge_diagonal() +
geom_node_point(size = 3) +
theme_graph()
小结:ggraph提供ggplot2风格的网络图绘制。
选择合适的网络布局。
# 创建网络
set.seed(123)
g <- sample_pa(50, directed = FALSE)
# 力导向布局(Fruchterman-Reingold)
ggraph(g, layout = "fr") +
geom_edge_link(alpha = 0.3) +
geom_node_point(size = 2, color = "steelblue") +
labs(title = "力导向布局 (FR)") +
theme_graph()
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
# 圆形布局
ggraph(g, layout = "circle") +
geom_edge_link(alpha = 0.3) +
geom_node_point(size = 2, color = "steelblue") +
labs(title = "圆形布局") +
theme_graph()
# 树形布局
g_tree <- make_tree(20, children = 2)
ggraph(g_tree, layout = "dendrogram") +
geom_edge_diagonal() +
geom_node_point(size = 2, color = "steelblue") +
labs(title = "树形布局") +
theme_graph()
# 网格布局
ggraph(g, layout = "grid") +
geom_edge_link(alpha = 0.3) +
geom_node_point(size = 2, color = "steelblue") +
labs(title = "网格布局") +
theme_graph()
小结:不同布局算法适用于不同类型的网络。
自定义网络图的外观。
# 创建带属性的网络
set.seed(123)
g <- sample_pa(30, directed = FALSE)
# 添加节点属性
V(g)$degree <- degree(g)
V(g)$community <- membership(cluster_louvain(g))
V(g)$name <- paste0("N", 1:30)
# 添加边属性
E(g)$weight <- runif(ecount(g), 1, 5)
# 节点大小映射度数
ggraph(g, layout = "fr") +
geom_edge_link(aes(width = weight), alpha = 0.3) +
geom_node_point(aes(size = degree, color = factor(community))) +
scale_size_continuous(range = c(2, 10)) +
scale_color_brewer(palette = "Set1") +
labs(title = "节点大小映射度数") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 添加标签
ggraph(g, layout = "fr") +
geom_edge_link(alpha = 0.3) +
geom_node_point(aes(size = degree, color = factor(community))) +
geom_node_text(aes(label = name), size = 2, repel = TRUE) +
scale_size_continuous(range = c(2, 8)) +
labs(title = "带标签的网络图") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
小结:可以通过aes()映射节点和边的属性。
展示网络的社区结构。
# 创建网络并检测社区
set.seed(123)
g <- sample_pa(50, directed = FALSE)
comm <- cluster_louvain(g)
V(g)$community <- membership(comm)
# 按社区着色
ggraph(g, layout = "fr") +
geom_edge_link(alpha = 0.3) +
geom_node_point(aes(color = factor(community)), size = 3) +
scale_color_brewer(palette = "Set1", name = "社区") +
labs(title = "社区结构可视化") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 高亮社区边界
ggraph(g, layout = "fr") +
geom_mark_hull(aes(x = x, y = y, fill = factor(community)),
alpha = 0.2) +
geom_edge_link(alpha = 0.3) +
geom_node_point(aes(color = factor(community)), size = 3) +
scale_fill_brewer(palette = "Set1", name = "社区") +
scale_color_brewer(palette = "Set1", name = "社区") +
labs(title = "社区边界高亮") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 分组布局
ggraph(g, layout = "fr") +
geom_edge_link(alpha = 0.3) +
geom_node_point(aes(color = factor(community)), size = 3) +
facet_nodes(~community) +
scale_color_brewer(palette = "Set1") +
theme_graph()
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
小结:社区检测和高亮可以展示网络的结构特征。
可视化层次结构数据。
# 创建树形结构
g <- make_tree(20, children = 2)
# 树状图
ggraph(g, layout = "dendrogram") +
geom_edge_diagonal() +
geom_node_point(size = 2, color = "steelblue") +
labs(title = "树状图") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
# 圆形树状图
ggraph(g, layout = "dendrogram", circular = TRUE) +
geom_edge_diagonal() +
geom_node_point(aes(filter = leaf), size = 2, color = "steelblue") +
coord_fixed() +
labs(title = "圆形树状图") +
theme_graph()
# 添加标签
V(g)$name <- paste0("Node", 1:20)
ggraph(g, layout = "dendrogram") +
geom_edge_diagonal() +
geom_node_text(aes(label = name, filter = leaf), size = 2, hjust = 1) +
labs(title = "带标签的树状图") +
theme_graph()
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
小结:树状图适合展示层次结构数据。
创建旭日图。
# 创建层次数据
edges <- data.frame(
from = c("Root", "Root", "Root", "A", "A", "B", "B", "B"),
to = c("A", "B", "C", "A1", "A2", "B1", "B2", "B3")
)
g <- graph_from_data_frame(edges)
# 旭日图
ggraph(g, layout = "partition", circular = TRUE) +
geom_node_arc_bar(aes(fill = depth), color = "white") +
coord_fixed() +
scale_fill_viridis(option = "D", name = "层级") +
labs(title = "旭日图") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
# 矩形分区图
ggraph(g, layout = "partition") +
geom_node_tile(aes(fill = depth), color = "white") +
scale_fill_viridis(option = "D", name = "层级") +
labs(title = "矩形分区图") +
theme_graph()
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
小结:旭日图展示层次结构的比例关系。
创建矩形树图。
# treemapify包已在setup中加载
# 创建数据
data <- data.frame(
group = c("A", "A", "B", "B", "C", "C"),
subgroup = c("A1", "A2", "B1", "B2", "C1", "C2"),
value = c(30, 20, 25, 15, 20, 10)
)
# 矩形树图
ggplot(data, aes(area = value, fill = group, label = subgroup)) +
geom_treemap() +
geom_treemap_text() +
scale_fill_brewer(palette = "Set1", name = "组别") +
labs(title = "矩形树图")
# 嵌套矩形树图
ggplot(data, aes(area = value, fill = group, subgroup = subgroup, label = subgroup)) +
geom_treemap() +
geom_treemap_subgroup_border() +
geom_treemap_subgroup_text() +
geom_treemap_text() +
scale_fill_brewer(palette = "Set1", name = "组别") +
labs(title = "嵌套矩形树图")
小结:矩形树图展示层次结构的比例关系。
创建桑基图。
# 使用ggalluvial包创建桑基图
library(ggalluvial)
# 创建桑基数据
data <- data.frame(
node1 = c("A", "A", "B", "B"),
node2 = c("X", "Y", "X", "Y"),
value = c(10, 20, 15, 25)
)
# 桑基图
ggplot(data, aes(axis1 = node1, axis2 = node2, y = value)) +
geom_alluvium(aes(fill = node1), width = 1/12) +
geom_stratum(width = 1/12, fill = "grey", color = "white") +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
scale_x_discrete(limits = c("来源", "目标"), expand = c(0.05, 0.05)) +
scale_fill_brewer(palette = "Set1", name = "来源") +
labs(title = "桑基图", y = "数量") +
theme_minimal()
# 多层桑基图
data_multi <- data.frame(
stage1 = c("A", "A", "A", "B", "B", "B"),
stage2 = c("X", "X", "Y", "X", "Y", "Y"),
stage3 = c("M", "N", "M", "N", "M", "N"),
value = c(10, 15, 20, 12, 18, 25)
)
ggplot(data_multi, aes(axis1 = stage1, axis2 = stage2, axis3 = stage3, y = value)) +
geom_alluvium(aes(fill = stage1), width = 1/12) +
geom_stratum(width = 1/12, fill = "grey", color = "white") +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
scale_x_discrete(limits = c("阶段1", "阶段2", "阶段3"), expand = c(0.05, 0.05)) +
scale_fill_brewer(palette = "Set1", name = "阶段1") +
labs(title = "多层桑基图", y = "数量") +
theme_minimal()
小结:桑基图展示流量和转移关系。
本章介绍如何可视化统计模型的结果和诊断信息。
可视化线性回归的诊断信息。
# 基础诊断图
model <- lm(hwy ~ displ + cyl, data = mpg)
# 基础R诊断图
par(mfrow = c(2, 2))
plot(model)
par(mfrow = c(1, 1))
# 使用ggplot2
library(ggplot2)
library(broom)
# 获取诊断数据
diag_data <- augment(model)
# 残差vs拟合值
ggplot(diag_data, aes(x = .fitted, y = .resid)) +
geom_point() +
geom_smooth(se = FALSE) +
geom_hline(yintercept = 0, linetype = "dashed") +
labs(x = "拟合值", y = "残差")
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
# Q-Q图
ggplot(diag_data, aes(sample = .resid)) +
stat_qq() +
stat_qq_line() +
labs(x = "理论分位数", y = "样本分位数")
# 使用autoplot
# library(ggfortify)
# autoplot(model)
小结:残差图和Q-Q图是诊断线性回归的重要工具。
详细的残差分析。
library(ggplot2)
library(broom)
model <- lm(hwy ~ displ + cyl, data = mpg)
diag_data <- augment(model)
# 残差vs拟合值
ggplot(diag_data, aes(x = .fitted, y = .resid)) +
geom_point(alpha = 0.5) +
geom_smooth(se = FALSE, color = "red") +
geom_hline(yintercept = 0, linetype = "dashed", color = "blue") +
labs(title = "残差 vs 拟合值", x = "拟合值", y = "残差")
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
# 标准化残差
ggplot(diag_data, aes(x = .fitted, y = .std.resid)) +
geom_point(alpha = 0.5) +
geom_hline(yintercept = c(-2, 0, 2), linetype = "dashed", color = "red") +
labs(title = "标准化残差", x = "拟合值", y = "标准化残差")
# 尺度位置图
ggplot(diag_data, aes(x = .fitted, y = sqrt(abs(.std.resid)))) +
geom_point(alpha = 0.5) +
geom_smooth(se = FALSE, color = "red") +
labs(title = "尺度位置图", x = "拟合值", y = expression(sqrt("|标准化残差|")))
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
# 残差vs杠杆
ggplot(diag_data, aes(x = .hat, y = .std.resid)) +
geom_point(alpha = 0.5) +
geom_smooth(se = FALSE, color = "red") +
geom_hline(yintercept = 0, linetype = "dashed") +
labs(title = "残差 vs 杠杆值", x = "杠杆值", y = "标准化残差")
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
小结:残差分析帮助检验模型假设。
可视化回归系数。
library(ggplot2)
library(broom)
model <- lm(hwy ~ displ + cyl + drv, data = mpg)
coef_data <- tidy(model, conf.int = TRUE)
# 系数点图
ggplot(coef_data, aes(x = estimate, y = term)) +
geom_point() +
geom_errorbarh(aes(xmin = conf.low, xmax = conf.high), height = 0.2) +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "系数估计", y = "")
## Warning: `geom_errorbarh()` was deprecated in ggplot2 4.0.0.
## ℹ Please use the `orientation` argument of `geom_errorbar()` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `height` was translated to `width`.
# 森林图风格
ggplot(coef_data, aes(x = estimate, y = term)) +
geom_point(size = 3) +
geom_errorbarh(aes(xmin = conf.low, xmax = conf.high), height = 0.2) +
geom_vline(xintercept = 0, linetype = "dashed", color = "red") +
theme_minimal() +
labs(x = "系数估计", y = "", title = "回归系数")
## `height` was translated to `width`.
# 使用dotwhisker包
# library(dotwhisker)
# dwplot(model)
小结:系数图直观展示回归系数和置信区间。
可视化ANOVA结果。
library(ggplot2)
# 单因素方差分析
aov_result <- aov(hwy ~ class, data = mpg)
# 均值比较图
ggplot(mpg, aes(x = class, y = hwy)) +
geom_boxplot() +
stat_summary(fun = mean, geom = "point", color = "red", size = 3)
# 带置信区间的均值图
library(dplyr)
means <- mpg %>%
group_by(class) %>%
summarise(
mean = mean(hwy),
se = sd(hwy) / sqrt(n()),
n = n()
)
ggplot(means, aes(x = class, y = mean)) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = mean - se, ymax = mean + se), width = 0.2) +
labs(y = "平均油耗", x = "车型类别")
# 使用ggpubr添加显著性标记
# library(ggpubr)
# ggboxplot(mpg, x = "class", y = "hwy", add = "jitter") +
# stat_compare_means(method = "anova")
小结:ANOVA结果可以用箱线图和均值图展示。
可视化PCA结果。
# 使用prcomp进行PCA
pca_result <- prcomp(mtcars[, 1:7], scale. = TRUE)
# 基础双标图
biplot(pca_result, main = "PCA双标图")
# 使用factoextra包可视化
# 变量贡献图
fviz_pca_var(pca_result,
col.var = "contrib",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
title = "变量贡献图")
# 个体图
fviz_pca_ind(pca_result,
col.ind = "cos2",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
title = "样本分布图")
# 双标图
fviz_pca_biplot(pca_result,
repel = TRUE,
title = "PCA双标图")
小结:双标图展示PCA的变量和样本信息。
可视化聚类结果。
# 层次聚类
hc <- hclust(dist(mtcars), method = "ward.D2")
# 基础树状图
plot(hc, main = "层次聚类树状图", xlab = "样本", sub = "")
# 使用factoextra可视化
# 矩形树状图
fviz_dend(hc, k = 4, cex = 0.5, k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE, rect = TRUE, rect_border = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
main = "聚类树状图(4类)")
# 环形树状图
fviz_dend(hc, k = 4, cex = 0.5, type = "circular",
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
main = "环形聚类树状图")
# K均值聚类
set.seed(123)
km <- kmeans(mtcars[, 1:4], centers = 3, nstart = 25)
# 聚类结果可视化
fviz_cluster(km, data = mtcars[, 1:4],
ellipse.type = "convex",
palette = "jco",
ggtheme = theme_minimal(),
main = "K均值聚类结果")
小结:树状图和聚类图展示聚类结构。
可视化随机森林的变量重要性。
# 随机森林模型
set.seed(123)
# importance=TRUE 才会输出完整的重要性矩阵
rf <- randomForest(Species ~ ., data = iris, ntree = 100, importance = TRUE)
# 查看变量重要性的列名
colnames(importance(rf))
## [1] "setosa" "versicolor" "virginica"
## [4] "MeanDecreaseAccuracy" "MeanDecreaseGini"
# 变量重要性矩阵
importance(rf)
## setosa versicolor virginica MeanDecreaseAccuracy
## Sepal.Length 2.334999 3.8525315 3.909442 5.331391
## Sepal.Width 1.873228 -0.2344981 2.931587 2.299106
## Petal.Length 9.062834 14.1250709 10.997897 13.197705
## Petal.Width 11.214854 14.2553890 16.251155 16.117169
## MeanDecreaseGini
## Sepal.Length 10.133410
## Sepal.Width 2.021934
## Petal.Length 39.955902
## Petal.Width 47.133554
# 基础变量重要性图
varImpPlot(rf, main = "随机森林变量重要性")
# 使用ggplot2可视化 MeanDecreaseGini
imp_df <- data.frame(
variable = rownames(importance(rf)),
importance = importance(rf)[, "MeanDecreaseGini"]
)
ggplot(imp_df, aes(x = reorder(variable, importance), y = importance)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(x = "变量", y = "重要性 (MeanDecreaseGini)",
title = "随机森林变量重要性") +
theme_minimal()
# 使用ggplot2可视化 MeanDecreaseAccuracy
imp_df2 <- data.frame(
variable = rownames(importance(rf)),
importance = importance(rf)[, "MeanDecreaseAccuracy"]
)
ggplot(imp_df2, aes(x = reorder(variable, importance), y = importance)) +
geom_col(fill = "coral") +
coord_flip() +
labs(x = "变量", y = "重要性 (MeanDecreaseAccuracy)",
title = "随机森林变量重要性(准确率下降)") +
theme_minimal()
小结:变量重要性图展示各变量的贡献程度。
可视化分类模型的混淆矩阵。
# 创建混淆矩阵数据
conf_matrix <- data.frame(
Predicted = rep(c("A", "B", "C"), each = 3),
Actual = rep(c("A", "B", "C"), 3),
Count = c(50, 5, 2, 3, 45, 4, 1, 3, 40)
)
# 热图展示
ggplot(conf_matrix, aes(x = Predicted, y = Actual, fill = Count)) +
geom_tile() +
geom_text(aes(label = Count), color = "white", size = 5) +
scale_fill_gradient(low = "white", high = "steelblue") +
theme_minimal()
# 使用caret包
# library(caret)
# confusion_matrix <- confusionMatrix(predictions, actual)
# fourfoldplot(confusion_matrix$table)
小结:混淆矩阵热图直观展示分类结果。
可视化ROC曲线。
# 创建模拟数据
set.seed(123)
actual <- sample(c(0, 1), 100, replace = TRUE)
predicted_prob <- runif(100)
# 创建ROC对象
roc_obj <- roc(actual, predicted_prob, quiet = TRUE)
# 基础ROC曲线
plot(roc_obj, main = "ROC曲线", col = "#2E9FDF", lwd = 2)
# 计算AUC
auc_value <- auc(roc_obj)
text(0.6, 0.3, paste("AUC =", round(auc_value, 3)), cex = 1.2)
# 使用ggplot2绑定ROC曲线
roc_df <- data.frame(
specificity = 1 - roc_obj$specificities,
sensitivity = roc_obj$sensitivities
)
ggplot(roc_df, aes(x = specificity, y = sensitivity)) +
geom_line(color = "#2E9FDF", size = 1.2) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray") +
annotate("text", x = 0.7, y = 0.3,
label = paste("AUC =", round(auc_value, 3)),
size = 5) +
labs(x = "1 - 特异度", y = "敏感度", title = "ROC曲线") +
theme_minimal() +
coord_equal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# 多模型比较(模拟)
roc_obj2 <- roc(actual, runif(100), quiet = TRUE)
ggroc(list(模型1 = roc_obj, 模型2 = roc_obj2)) +
scale_color_brewer(palette = "Set1", name = "模型") +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray") +
labs(title = "多模型ROC曲线比较") +
theme_minimal()
小结:ROC曲线评估分类模型性能。
可视化生存分析结果。
# 使用survival和survminer包(已在setup中加载)
# 使用lung数据集
data(lung)
## Warning in data(lung): data set 'lung' not found
# 创建生存对象
fit <- survfit(Surv(time, status) ~ sex, data = lung)
# 基础生存曲线
ggsurvplot(fit,
data = lung,
title = "生存曲线",
xlab = "时间(天)",
ylab = "生存概率",
legend.title = "性别",
legend.labs = c("男性", "女性"),
ggtheme = theme_minimal())
# 完整生存曲线
ggsurvplot(fit,
data = lung,
pval = TRUE, # 添加p值
conf.int = TRUE, # 添加置信区间
risk.table = TRUE, # 添加风险表
title = "完整生存曲线",
xlab = "时间(天)",
ylab = "生存概率",
legend.title = "性别",
legend.labs = c("男性", "女性"),
ggtheme = theme_minimal())
## Ignoring unknown labels:
## • colour : "性别"
# 累积风险曲线
ggsurvplot(fit,
fun = "cumhaz",
data = lung,
title = "累积风险曲线",
xlab = "时间(天)",
ylab = "累积风险",
legend.title = "性别",
legend.labs = c("男性", "女性"),
ggtheme = theme_minimal())
小结:生存曲线展示生存分析结果。
对比预测值和实际值。
library(ggplot2)
model <- lm(hwy ~ displ + cyl, data = mpg)
pred_data <- data.frame(
actual = mpg$hwy,
predicted = predict(model)
)
# 散点图对比
ggplot(pred_data, aes(x = actual, y = predicted)) +
geom_point(alpha = 0.5) +
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") +
labs(x = "实际值", y = "预测值", title = "预测 vs 实际")
# 残差分布
pred_data$residual <- pred_data$actual - pred_data$predicted
ggplot(pred_data, aes(x = residual)) +
geom_histogram(bins = 30, fill = "steelblue", alpha = 0.7) +
geom_vline(xintercept = 0, color = "red", linetype = "dashed") +
labs(x = "残差", y = "频数")
小结:预测对比图评估模型预测能力。
本章介绍如何优化可视化性能和遵循最佳实践。
处理大数据集的策略。
library(ggplot2)
# 创建大数据集
set.seed(123)
big_data <- data.frame(
x = rnorm(100000),
y = rnorm(100000),
group = sample(letters[1:5], 100000, replace = TRUE)
)
# 策略1:抽样
sample_data <- big_data[sample(nrow(big_data), 5000), ]
ggplot(sample_data, aes(x = x, y = y)) +
geom_point(alpha = 0.3)
# 策略2:分箱
ggplot(big_data, aes(x = x, y = y)) +
geom_bin2d(bins = 50)
# 策略3:透明度
ggplot(big_data, aes(x = x, y = y)) +
geom_point(alpha = 0.01)
# 策略4:六边形分箱
# ggplot(big_data, aes(x = x, y = y)) +
# geom_hex(bins = 50)
小结:抽样、分箱和透明度是处理大数据集的常用策略。
优化散点图性能。
library(ggplot2)
set.seed(123)
big_data <- data.frame(
x = rnorm(50000),
y = rnorm(50000)
)
# 低透明度
ggplot(big_data, aes(x = x, y = y)) +
geom_point(alpha = 0.05)
# 使用光栅化(需要ragg包)
# install.packages("ragg")
# library(ragg)
# ggsave("plot.png",
# ggplot(big_data, aes(x = x, y = y)) +
# geom_point(alpha = 0.05),
# device = agg_png,
# width = 8, height = 6, dpi = 300)
小结:透明度和光栅化可以优化大数据散点图。
预先聚合数据提高性能。
# 使用data.table
# install.packages("data.table")
# library(data.table)
# 创建大数据
# big_dt <- data.table(x = rnorm(1e6), group = sample(letters, 1e6, replace = TRUE))
# 聚合
# agg_data <- big_dt[, .(mean = mean(x), sd = sd(x), n = .N), by = group]
# 可视化聚合结果
# ggplot(agg_data, aes(x = group, y = mean)) +
# geom_col()
小结:预先聚合可以大幅提高可视化性能。
选择合适的图形格式。
library(ggplot2)
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# 矢量图格式
# PDF:适合打印和出版
ggsave("plot.pdf", p, width = 8, height = 6)
# SVG:适合网页
ggsave("plot.svg", p, width = 8, height = 6)
# 位图格式
# PNG:通用格式,支持透明
ggsave("plot.png", p, width = 8, height = 6, dpi = 300)
# JPEG:照片类图像,不支持透明
ggsave("plot.jpg", p, width = 8, height = 6, dpi = 300)
# TIFF:高质量印刷
ggsave("plot.tiff", p, width = 8, height = 6, dpi = 300)
# 格式选择建议
# 矢量图(PDF/SVG):适合线条图、小数据量
# 位图(PNG):适合大数据量、网页展示
# 高分辨率(300+ dpi):适合印刷
小结:矢量图适合印刷,位图适合大数据和网页。
正确设置图形参数。
library(ggplot2)
p <- ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point()
# 设置DPI
ggsave("plot_low.png", p, dpi = 72) # 网页
ggsave("plot_high.png", p, dpi = 300) # 印刷
ggsave("plot_print.png", p, dpi = 600) # 高质量印刷
# 设置尺寸(英寸)
ggsave("plot.png", p, width = 10, height = 8, dpi = 300)
# 设置单位
ggsave("plot_cm.png", p, width = 25, height = 20, units = "cm", dpi = 300)
# 使用cairo设备(更好的字体支持)
ggsave("plot_cairo.png", p, type = "cairo", dpi = 300)
小结:根据用途选择合适的DPI和尺寸。
遵循配色最佳实践。
library(ggplot2)
# 色盲友好配色
# 使用viridis或ColorBrewer色盲友好调色板
# 分类数据
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point() +
scale_color_brewer(palette = "Set2") # 色盲友好
# 连续数据
ggplot(mpg, aes(x = displ, y = hwy, color = cty)) +
geom_point() +
scale_color_viridis_c() # 色盲友好
# 配色原则
# 1. 避免使用红绿对比(色盲问题)
# 2. 使用感知均匀的颜色渐变
# 3. 分类颜色应有足够对比度
# 4. 考虑黑白打印效果
小结:使用色盲友好的配色方案。
创建清晰的标签。
library(ggplot2)
# 清晰的标签示例
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
labs(
title = "发动机排量与油耗的关系",
subtitle = "数据来源:EPA燃料经济数据",
x = "发动机排量 (升)",
y = "高速公路油耗 (英里/加仑)",
caption = "图1:散点图展示排量与油耗的负相关关系"
) +
theme_minimal()
# 标签原则
# 1. 使用描述性标题
# 2. 包含单位
# 3. 添加数据来源
# 4. 使用适当的字体大小
小结:清晰的标签帮助读者理解图形。
保持图形简洁。
library(ggplot2)
# 过度装饰的图形(避免)
ggplot(mpg, aes(x = class, y = hwy)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(title = "各类车型油耗", x = "车型", y = "油耗") +
theme(
panel.background = element_rect(fill = "lightyellow"),
panel.grid.major = element_line(color = "pink"),
panel.grid.minor = element_line(color = "lightpink"),
plot.background = element_rect(fill = "lightgray")
)
# 简洁清晰的图形(推荐)
ggplot(mpg, aes(x = reorder(class, hwy), y = hwy)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(title = "各类车型平均油耗", x = "车型", y = "油耗 (英里/加仑)") +
theme_minimal() +
coord_flip()
小结:简洁的图形更有效传达信息。
确保图形可重复。
# 创建可重复的图形脚本
# 1. 设置随机种子
set.seed(123)
# 2. 记录包版本
# sessionInfo()
# 3. 使用相对路径
# data <- read.csv("data/mydata.csv")
# 4. 封装绘图函数
create_scatter_plot <- function(data, x_var, y_var, color_var = NULL) {
p <- ggplot(data, aes_string(x = x_var, y = y_var, color = color_var)) +
geom_point() +
theme_minimal()
return(p)
}
# 使用函数
# p <- create_scatter_plot(mpg, "displ", "hwy", "drv")
# print(p)
# 5. 保存图形和代码
# ggsave("output/plot.png", p)
# saveRDS(p, "output/plot.rds") # 保存图形对象
小结:脚本化确保图形可重复生成。
创建可重用的图形模板。
library(ggplot2)
# 定义主题模板
theme_publication <- function() {
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
}
# 定义散点图模板
scatter_template <- function(data, x, y, color = NULL,
title = "", xlab = "", ylab = "") {
ggplot(data, aes_string(x = x, y = y, color = color)) +
geom_point(alpha = 0.7, size = 2) +
geom_smooth(method = "lm", se = TRUE, alpha = 0.2) +
labs(title = title, x = xlab, y = ylab) +
theme_publication()
}
# 使用模板
scatter_template(mpg, "displ", "hwy", "drv",
title = "排量与油耗关系",
xlab = "发动机排量 (升)",
ylab = "高速公路油耗")
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using formula = 'y ~ x'
# 定义柱状图模板
bar_template <- function(data, x, y, fill = NULL,
title = "", xlab = "", ylab = "") {
ggplot(data, aes_string(x = x, y = y, fill = fill)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = title, x = xlab, y = ylab) +
theme_publication() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
}
小结:自定义模板提高效率和一致性。
本教程全面介绍了R语言数据可视化的核心内容:
基础部分: - 基础绘图系统(base graphics) - ggplot2图形语法 - 常用统计图形
进阶部分: - 图形属性与标度 - 坐标系与分面 - 主题定制 - 多图组合
高级部分: - 颜色与字体控制 - 交互式可视化 - 高级图表类型 - 动态可视化 - 空间数据可视化 - 网络可视化 - 模型诊断可视化
最佳实践: - 性能优化 - 配色原则 - 可重复性
希望本教程能帮助您掌握R语言数据可视化的核心技能!
作者:小天使格礼
参考资源: - ggplot2官方文档:https://ggplot2.tidyverse.org/ - R Graph Gallery:https://r-graph-gallery.com/ - R Color Brewer:https://colorbrewer2.org/