install.packages("ggplot2")
install.packages("dplyr")
install.packages("GGally")
install.packages("corrplot")
install.packages("vcd")R语言绘图:标注、气泡图、散点图矩阵、相关图、马赛克图与图形修改
1. 本节学习目标
本节学习以下图形:
- 图 + 标注
- 气泡图
- 散点图矩阵
- 分组散点图
- 相关图
- 马赛克图
- 图形修改与美化
主要用到这些包:
ggplot2
dplyr
GGally
corrplot
vcd其中:
| 包 | 作用 |
|---|---|
ggplot2 |
基础绘图 |
dplyr |
数据整理 |
GGally |
散点图矩阵 |
corrplot |
相关图 |
vcd |
马赛克图,尤其是带残差着色的马赛克图 |
说明:
- 基础马赛克图使用 R 自带的
mosaicplot(); vcd::mosaic()功能更丰富,可以进行残差着色;- 但在某些中文标签或多维列联表场景下,
vcd::mosaic()在 Knit 时可能出现兼容性问题; - 因此本文保留
vcd示例,但不自动执行vcd::mosaic()代码。
2. 安装和加载包
如果没有安装,可以先运行:
加载基础包:
library(ggplot2)
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
检查后面会用到的扩展包:
if (!requireNamespace("GGally", quietly = TRUE)) {
message("未安装 GGally,散点图矩阵部分将不会绘图。")
}
if (!requireNamespace("corrplot", quietly = TRUE)) {
message("未安装 corrplot,相关图部分将不会绘图。")
}
if (!requireNamespace("vcd", quietly = TRUE)) {
message("未安装 vcd,vcd 示例代码仅展示,不影响本文运行。")
}3. 创建示例数据
我们创建一个学生数据集。
set.seed(123)
student <- data.frame(
id = 1:120,
class = rep(c("一班", "二班", "三班"), each = 40),
gender = sample(c("男", "女"), 120, replace = TRUE),
group = sample(c("实验组", "对照组"), 120, replace = TRUE),
chinese = round(rnorm(120, mean = 82, sd = 8), 1),
math = round(rnorm(120, mean = 80, sd = 10), 1),
english = round(rnorm(120, mean = 84, sd = 7), 1),
height = round(rnorm(120, mean = 168, sd = 8), 1),
weight = round(rnorm(120, mean = 62, sd = 10), 1)
)
student$total <- student$chinese + student$math + student$english
student$average <- round(student$total / 3, 1)
student$class <- factor(
student$class,
levels = c("一班", "二班", "三班"),
ordered = TRUE
)
head(student,5) id class gender group chinese math english height weight total average
1 1 一班 男 实验组 82.9 72.1 82.6 168.2 72.7 237.6 79.2
2 2 一班 男 对照组 74.4 75.0 88.6 170.5 61.7 238.0 79.3
3 3 一班 男 实验组 78.1 95.0 85.9 178.6 61.7 259.0 86.3
4 4 一班 女 实验组 80.0 68.6 91.2 169.0 46.8 239.8 79.9
5 5 一班 男 实验组 96.8 78.2 89.7 173.7 69.9 264.7 88.2
查看数据结构:
str(student)'data.frame': 120 obs. of 11 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
$ class : Ord.factor w/ 3 levels "一班"<"二班"<..: 1 1 1 1 1 1 1 1 1 1 ...
$ gender : chr "男" "男" "男" "女" ...
$ group : chr "实验组" "对照组" "实验组" "实验组" ...
$ chinese: num 82.9 74.4 78.1 80 96.8 76.8 83.9 82.6 74.3 81.4 ...
$ math : num 72.1 75 95 68.6 78.2 99 79 66.4 73.4 84.9 ...
$ english: num 82.6 88.6 85.9 91.2 89.7 82.5 86.6 77.4 90 80.8 ...
$ height : num 168 170 179 169 174 ...
$ weight : num 72.7 61.7 61.7 46.8 69.9 59.9 55.4 47.9 59 53.5 ...
$ total : num 238 238 259 240 265 ...
$ average: num 79.2 79.3 86.3 79.9 88.2 86.1 83.2 75.5 79.2 82.4 ...
4. 图 + 标注
4.1 什么是图形标注?
图形标注就是在图中添加文字说明,例如:
- 给某个点添加名字;
- 给柱子添加数值;
- 标出最高分;
- 添加参考线;
- 添加解释性文字。
常用函数:
| 函数 | 作用 |
|---|---|
geom_text() |
添加文字 |
geom_label() |
添加带边框的标签 |
annotate() |
添加固定文字或图形 |
geom_vline() |
添加竖线 |
geom_hline() |
添加横线 |
geom_abline() |
添加斜线 |
4.2 散点图 + 文字标注
ggplot(student, aes(x = chinese, y = math)) +
geom_point() +
labs(
title = "语文成绩与数学成绩散点图",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()给每个点标注学生编号:
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue") +
geom_text(
aes(label = id),
vjust = -0.5,
size = 3
) +
labs(
title = "语文成绩与数学成绩散点图:标注学生编号",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()点太多时不建议给每个点都标注,会比较拥挤。
4.3 只标注高分学生
比如只标注平均分大于 95 的学生。
high_student <- student %>%
filter(average > 95)
high_student id class gender group chinese math english height weight total average
1 111 三班 女 实验组 97.6 90.1 97.8 145.5 72.6 285.5 95.2
画图:
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "grey50", alpha = 0.7) +
geom_point(
data = high_student,
color = "red",
size = 3
) +
geom_text(
data = high_student,
aes(label = id),
vjust = -0.6,
color = "red",
size = 4
) +
labs(
title = "只标注平均分大于95的学生",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()解释:
- 第一层
geom_point()画所有学生; - 第二层
geom_point(data = high_student)突出高分学生; - 第三层
geom_text(data = high_student)给高分学生加标签。
4.4 使用 geom_label() 添加标签
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "grey50", alpha = 0.7) +
geom_label(
data = high_student,
aes(label = paste0("ID=", id)),
fill = "yellow",
color = "red",
size = 3
) +
labs(
title = "使用 geom_label() 标注高分学生",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()4.5 添加参考线
添加数学 80 分横线和语文 80 分竖线。
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue", alpha = 0.7) +
geom_hline(
yintercept = 80,
linetype = "dashed",
color = "red"
) +
geom_vline(
xintercept = 80,
linetype = "dashed",
color = "red"
) +
labs(
title = "语文和数学成绩散点图:添加80分参考线",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()4.6 使用 annotate() 添加说明文字
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue", alpha = 0.7) +
geom_hline(yintercept = 80, linetype = "dashed", color = "red") +
geom_vline(xintercept = 80, linetype = "dashed", color = "red") +
annotate(
"text",
x = 95,
y = 70,
label = "红线表示80分",
color = "red",
size = 5
) +
labs(
title = "使用 annotate() 添加说明文字",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()5. 气泡图
5.1 什么是气泡图?
气泡图本质上是散点图。
区别是:
散点图用 x 和 y 表示两个变量;
气泡图额外用点的大小表示第三个变量。
例如:
- 横轴:语文成绩;
- 纵轴:数学成绩;
- 气泡大小:英语成绩;
- 颜色:班级。
5.2 基础气泡图
ggplot(student, aes(x = chinese, y = math, size = english)) +
geom_point(alpha = 0.6) +
labs(
title = "气泡图:语文、数学和英语成绩",
x = "语文成绩",
y = "数学成绩",
size = "英语成绩"
) +
theme_minimal()5.3 分组气泡图
ggplot(student, aes(x = chinese, y = math, size = english, color = class)) +
geom_point(alpha = 0.6) +
labs(
title = "气泡图:颜色表示班级,大小表示英语成绩",
x = "语文成绩",
y = "数学成绩",
size = "英语成绩",
color = "班级"
) +
theme_minimal()5.4 调整气泡大小范围
ggplot(student, aes(x = chinese, y = math, size = english, color = class)) +
geom_point(alpha = 0.6) +
scale_size_continuous(range = c(2, 10)) +
labs(
title = "调整气泡大小范围",
x = "语文成绩",
y = "数学成绩",
size = "英语成绩",
color = "班级"
) +
theme_minimal()解释:
scale_size_continuous(range = c(2, 10))表示最小气泡大小为 2,最大气泡大小为 10。
5.5 气泡图 + 趋势线
ggplot(student, aes(x = chinese, y = math)) +
geom_point(
aes(size = english, color = class),
alpha = 0.5
) +
geom_smooth(
aes(group = 1),
method = "lm",
se = TRUE,
color = "black",
linewidth = 1
) +
scale_size_continuous(range = c(2, 10)) +
labs(
title = "气泡图 + 总体线性趋势线",
x = "语文成绩",
y = "数学成绩",
size = "英语成绩",
color = "班级"
) +
theme_minimal()`geom_smooth()` using formula = 'y ~ x'
解释:
method = "lm"表示添加线性回归趋势线;aes(group = 1)表示画一条总体趋势线,而不是每个班级一条。
6. 分组散点图
6.1 什么是分组散点图?
分组散点图是在散点图中用颜色、形状或分面表示不同组。
例如:
- 用颜色表示班级;
- 用形状表示性别;
- 用分面分别展示实验组和对照组。
6.2 用颜色分组
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
labs(
title = "分组散点图:颜色表示班级",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()6.3 用形状分组
ggplot(student, aes(x = chinese, y = math, shape = gender)) +
geom_point(size = 2, alpha = 0.7) +
labs(
title = "分组散点图:形状表示性别",
x = "语文成绩",
y = "数学成绩",
shape = "性别"
) +
theme_minimal()6.4 颜色 + 形状同时分组
ggplot(student, aes(x = chinese, y = math, color = class, shape = gender)) +
geom_point(size = 2.5, alpha = 0.8) +
labs(
title = "分组散点图:颜色表示班级,形状表示性别",
x = "语文成绩",
y = "数学成绩",
color = "班级",
shape = "性别"
) +
theme_minimal()6.5 分组散点图 + 趋势线
每个班级一条趋势线:
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE) +
labs(
title = "不同班级语文与数学关系趋势线",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()`geom_smooth()` using formula = 'y ~ x'
只画一条总体趋势线:
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
geom_smooth(
aes(group = 1),
method = "lm",
se = FALSE,
color = "black"
) +
labs(
title = "分组散点图 + 总体趋势线",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()`geom_smooth()` using formula = 'y ~ x'
6.6 分面散点图
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
facet_wrap(~ group) +
labs(
title = "按照实验组/对照组分面的散点图",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()7. 散点图矩阵
7.1 什么是散点图矩阵?
散点图矩阵用于同时查看多个连续变量之间的关系。
例如同时查看:
- 语文;
- 数学;
- 英语;
- 身高;
- 体重;
- 平均分。
散点图矩阵适合初步探索多个数值变量之间的相关关系。
7.2 使用 GGally::ggpairs()
选择数值变量:
score_vars <- student %>%
select(chinese, math, english, height, weight, average)
score_vars chinese math english height weight average
1 82.9 72.1 82.6 168.2 72.7 79.2
2 74.4 75.0 88.6 170.5 61.7 79.3
3 78.1 95.0 85.9 178.6 61.7 86.3
4 80.0 68.6 91.2 169.0 46.8 79.9
5 96.8 78.2 89.7 173.7 69.9 88.2
6 76.8 99.0 82.5 174.2 59.9 86.1
7 83.9 79.0 86.6 175.3 55.4 83.2
8 82.6 66.4 77.4 163.4 47.9 75.5
9 74.3 73.4 90.0 181.0 59.0 79.2
10 81.4 84.9 80.8 165.0 53.5 82.4
11 93.6 76.2 100.9 167.2 58.0 90.2
12 85.6 74.4 72.4 179.2 49.8 77.5
13 82.3 76.6 80.8 178.4 78.9 79.9
14 78.6 80.9 89.8 159.3 61.8 83.1
15 65.6 96.0 87.6 161.0 72.7 83.1
16 91.1 79.1 79.9 157.1 36.0 83.4
17 70.3 90.8 77.0 169.5 57.5 79.4
18 87.9 86.3 85.0 169.3 55.2 86.4
19 97.3 78.9 83.9 170.9 49.8 86.7
20 70.4 64.7 71.5 172.4 77.5 68.9
21 87.6 74.8 84.2 163.2 47.8 82.2
22 79.9 75.1 85.3 160.1 65.2 80.1
23 69.4 80.5 85.2 176.2 70.5 78.4
24 69.9 93.0 76.6 174.0 63.8 79.8
25 69.2 102.9 87.3 155.9 53.2 86.5
26 77.8 95.5 93.6 167.2 71.4 89.0
27 70.3 78.7 87.2 160.8 63.7 78.7
28 87.5 62.4 76.1 151.4 51.4 75.3
29 98.8 76.1 81.0 169.2 48.1 85.3
30 71.7 80.9 86.4 167.4 82.9 79.7
31 88.3 88.5 79.5 167.2 55.2 85.4
32 88.2 89.6 68.9 169.7 43.4 82.2
33 84.7 86.8 90.2 175.1 67.3 87.2
34 73.9 66.0 78.2 169.6 65.1 72.7
35 81.0 88.5 80.0 163.1 48.5 83.2
36 79.8 75.5 94.5 162.1 42.6 83.3
37 86.5 81.7 78.6 166.9 60.8 82.3
38 79.0 80.7 89.9 170.5 73.4 83.2
39 89.8 84.3 75.2 159.7 68.4 83.1
40 79.0 80.2 81.5 166.5 57.1 80.2
41 90.4 63.3 83.5 175.7 53.7 79.1
42 73.6 87.4 75.8 167.1 64.7 78.9
43 71.9 83.9 79.6 162.4 63.6 78.5
44 107.9 77.3 83.8 165.8 68.3 89.7
45 78.7 81.2 88.7 176.9 58.0 82.9
46 84.4 81.3 72.4 172.4 71.0 79.4
47 87.1 82.2 81.6 177.9 53.7 83.6
48 78.1 96.4 89.3 169.1 58.7 87.9
49 86.1 77.8 80.2 171.3 69.4 81.4
50 85.0 81.7 85.6 163.5 71.9 84.1
51 80.3 91.7 87.4 172.8 42.6 86.5
52 82.5 90.5 85.9 163.9 63.1 86.3
53 81.7 91.5 88.6 156.6 68.1 87.3
54 99.0 74.2 83.1 169.0 47.5 85.4
55 76.1 100.0 81.1 183.6 66.8 85.7
56 73.2 80.7 65.5 174.4 53.7 73.1
57 82.3 98.7 83.3 177.3 72.2 88.1
58 84.5 66.5 87.0 170.9 67.4 79.3
59 85.5 80.2 87.7 163.1 69.7 84.5
60 78.3 92.5 80.1 166.4 63.2 83.6
61 73.5 72.8 96.5 165.8 70.6 80.9
62 92.1 72.5 86.0 164.3 75.8 83.5
63 79.2 70.6 84.9 173.6 81.7 78.2
64 75.1 69.5 92.9 158.4 61.7 79.2
65 80.1 75.6 79.0 174.9 39.5 78.2
66 80.4 83.3 80.8 174.9 62.3 81.5
67 90.9 59.9 100.8 158.4 64.1 83.9
68 82.7 82.1 84.1 173.1 60.4 83.0
69 88.0 92.4 95.4 187.4 67.7 91.9
70 78.0 100.4 73.9 163.5 72.1 84.1
71 83.7 93.0 82.7 174.8 56.8 86.5
72 79.4 87.6 86.6 161.7 59.1 84.5
73 82.8 62.7 86.1 176.9 66.0 77.2
74 74.8 74.0 77.0 170.0 56.5 75.3
75 71.5 76.5 84.1 181.2 62.9 77.4
76 98.0 87.0 76.5 156.3 42.4 87.2
77 86.8 78.9 89.0 167.6 50.8 84.9
78 72.0 67.4 91.6 163.8 48.7 77.0
79 77.1 96.8 68.4 166.4 53.5 80.8
80 72.5 89.1 92.6 163.0 55.1 84.7
81 99.6 82.4 75.3 161.3 65.8 85.8
82 92.5 92.2 87.2 172.6 71.8 90.6
83 79.9 66.6 88.6 159.3 54.7 78.4
84 86.3 86.6 82.6 179.9 52.0 85.2
85 78.7 74.8 79.5 158.5 51.6 77.7
86 78.2 86.8 85.2 168.8 57.9 83.4
87 75.7 79.4 87.1 172.3 59.6 80.7
88 77.2 86.3 90.2 172.7 66.8 84.6
89 95.2 93.4 69.6 165.6 58.8 86.1
90 81.6 80.1 72.5 168.6 41.2 78.1
91 83.0 90.2 94.0 175.7 61.1 89.1
92 83.9 68.1 91.3 156.3 73.9 81.1
93 91.9 72.8 87.0 161.7 73.9 83.9
94 77.9 95.2 89.0 170.6 54.1 87.4
95 74.1 83.8 90.4 164.4 46.5 82.8
96 95.4 59.5 65.4 179.0 86.6 73.4
97 78.5 66.4 91.8 173.4 60.4 78.9
98 76.2 78.0 80.6 168.6 61.0 78.3
99 72.1 88.7 85.6 155.9 66.2 82.1
100 71.7 79.0 81.9 168.2 45.9 77.5
101 77.4 86.2 90.1 165.5 54.7 84.6
102 86.9 89.6 81.6 167.2 46.6 86.0
103 90.9 96.7 87.6 158.5 55.1 91.7
104 87.7 80.6 81.3 172.0 63.2 83.2
105 79.1 79.5 76.4 159.7 48.4 78.3
106 82.5 62.5 92.5 166.2 67.9 79.2
107 76.4 81.0 89.2 171.1 64.9 82.2
108 76.3 74.3 96.1 161.7 53.0 82.2
109 89.1 70.3 84.5 172.7 64.3 81.3
110 73.9 78.2 91.9 157.5 69.5 81.3
111 97.6 90.1 97.8 145.5 72.6 95.2
112 81.3 60.1 82.0 171.7 59.9 74.5
113 83.7 75.7 74.7 174.7 61.1 78.0
114 76.1 81.2 82.3 165.7 61.1 79.9
115 77.4 71.1 82.5 172.0 76.4 77.0
116 71.5 83.3 85.1 158.8 73.3 80.0
117 80.5 84.1 96.0 167.0 70.3 86.9
118 85.4 79.7 81.7 152.5 59.1 82.3
119 84.6 55.3 86.6 177.4 65.7 75.5
120 75.7 105.7 82.4 182.9 66.0 87.9
画散点图矩阵:
if (requireNamespace("GGally", quietly = TRUE)) {
GGally::ggpairs(score_vars)
} else {
message("未安装 GGally,因此不绘制散点图矩阵。")
}7.3 分组散点图矩阵
如果想按班级上色,可以把班级变量也放进去。
score_vars_group <- student %>%
select(class, chinese, math, english, height, weight, average)
if (requireNamespace("GGally", quietly = TRUE)) {
GGally::ggpairs(
score_vars_group,
aes(color = class, alpha = 0.6)
)
} else {
message("未安装 GGally,因此不绘制分组散点图矩阵。")
}`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
7.4 只选择部分变量画矩阵
变量太多时图会很拥挤,建议只选 3 到 5 个变量。
if (requireNamespace("GGally", quietly = TRUE)) {
GGally::ggpairs(
student,
columns = c("chinese", "math", "english", "average"),
aes(color = class, alpha = 0.6)
)
} else {
message("未安装 GGally,因此不绘制散点图矩阵。")
}8. 相关图
8.1 什么是相关图?
相关图用于展示多个连续变量之间的相关系数。
相关系数一般在 -1 到 1 之间:
| 相关系数 | 含义 |
|---|---|
| 接近 1 | 强正相关 |
| 接近 -1 | 强负相关 |
| 接近 0 | 几乎无线性相关 |
8.2 计算相关矩阵
先选择连续变量:
num_data <- student %>%
select(chinese, math, english, height, weight, total, average)
num_data chinese math english height weight total average
1 82.9 72.1 82.6 168.2 72.7 237.6 79.2
2 74.4 75.0 88.6 170.5 61.7 238.0 79.3
3 78.1 95.0 85.9 178.6 61.7 259.0 86.3
4 80.0 68.6 91.2 169.0 46.8 239.8 79.9
5 96.8 78.2 89.7 173.7 69.9 264.7 88.2
6 76.8 99.0 82.5 174.2 59.9 258.3 86.1
7 83.9 79.0 86.6 175.3 55.4 249.5 83.2
8 82.6 66.4 77.4 163.4 47.9 226.4 75.5
9 74.3 73.4 90.0 181.0 59.0 237.7 79.2
10 81.4 84.9 80.8 165.0 53.5 247.1 82.4
11 93.6 76.2 100.9 167.2 58.0 270.7 90.2
12 85.6 74.4 72.4 179.2 49.8 232.4 77.5
13 82.3 76.6 80.8 178.4 78.9 239.7 79.9
14 78.6 80.9 89.8 159.3 61.8 249.3 83.1
15 65.6 96.0 87.6 161.0 72.7 249.2 83.1
16 91.1 79.1 79.9 157.1 36.0 250.1 83.4
17 70.3 90.8 77.0 169.5 57.5 238.1 79.4
18 87.9 86.3 85.0 169.3 55.2 259.2 86.4
19 97.3 78.9 83.9 170.9 49.8 260.1 86.7
20 70.4 64.7 71.5 172.4 77.5 206.6 68.9
21 87.6 74.8 84.2 163.2 47.8 246.6 82.2
22 79.9 75.1 85.3 160.1 65.2 240.3 80.1
23 69.4 80.5 85.2 176.2 70.5 235.1 78.4
24 69.9 93.0 76.6 174.0 63.8 239.5 79.8
25 69.2 102.9 87.3 155.9 53.2 259.4 86.5
26 77.8 95.5 93.6 167.2 71.4 266.9 89.0
27 70.3 78.7 87.2 160.8 63.7 236.2 78.7
28 87.5 62.4 76.1 151.4 51.4 226.0 75.3
29 98.8 76.1 81.0 169.2 48.1 255.9 85.3
30 71.7 80.9 86.4 167.4 82.9 239.0 79.7
31 88.3 88.5 79.5 167.2 55.2 256.3 85.4
32 88.2 89.6 68.9 169.7 43.4 246.7 82.2
33 84.7 86.8 90.2 175.1 67.3 261.7 87.2
34 73.9 66.0 78.2 169.6 65.1 218.1 72.7
35 81.0 88.5 80.0 163.1 48.5 249.5 83.2
36 79.8 75.5 94.5 162.1 42.6 249.8 83.3
37 86.5 81.7 78.6 166.9 60.8 246.8 82.3
38 79.0 80.7 89.9 170.5 73.4 249.6 83.2
39 89.8 84.3 75.2 159.7 68.4 249.3 83.1
40 79.0 80.2 81.5 166.5 57.1 240.7 80.2
41 90.4 63.3 83.5 175.7 53.7 237.2 79.1
42 73.6 87.4 75.8 167.1 64.7 236.8 78.9
43 71.9 83.9 79.6 162.4 63.6 235.4 78.5
44 107.9 77.3 83.8 165.8 68.3 269.0 89.7
45 78.7 81.2 88.7 176.9 58.0 248.6 82.9
46 84.4 81.3 72.4 172.4 71.0 238.1 79.4
47 87.1 82.2 81.6 177.9 53.7 250.9 83.6
48 78.1 96.4 89.3 169.1 58.7 263.8 87.9
49 86.1 77.8 80.2 171.3 69.4 244.1 81.4
50 85.0 81.7 85.6 163.5 71.9 252.3 84.1
51 80.3 91.7 87.4 172.8 42.6 259.4 86.5
52 82.5 90.5 85.9 163.9 63.1 258.9 86.3
53 81.7 91.5 88.6 156.6 68.1 261.8 87.3
54 99.0 74.2 83.1 169.0 47.5 256.3 85.4
55 76.1 100.0 81.1 183.6 66.8 257.2 85.7
56 73.2 80.7 65.5 174.4 53.7 219.4 73.1
57 82.3 98.7 83.3 177.3 72.2 264.3 88.1
58 84.5 66.5 87.0 170.9 67.4 238.0 79.3
59 85.5 80.2 87.7 163.1 69.7 253.4 84.5
60 78.3 92.5 80.1 166.4 63.2 250.9 83.6
61 73.5 72.8 96.5 165.8 70.6 242.8 80.9
62 92.1 72.5 86.0 164.3 75.8 250.6 83.5
63 79.2 70.6 84.9 173.6 81.7 234.7 78.2
64 75.1 69.5 92.9 158.4 61.7 237.5 79.2
65 80.1 75.6 79.0 174.9 39.5 234.7 78.2
66 80.4 83.3 80.8 174.9 62.3 244.5 81.5
67 90.9 59.9 100.8 158.4 64.1 251.6 83.9
68 82.7 82.1 84.1 173.1 60.4 248.9 83.0
69 88.0 92.4 95.4 187.4 67.7 275.8 91.9
70 78.0 100.4 73.9 163.5 72.1 252.3 84.1
71 83.7 93.0 82.7 174.8 56.8 259.4 86.5
72 79.4 87.6 86.6 161.7 59.1 253.6 84.5
73 82.8 62.7 86.1 176.9 66.0 231.6 77.2
74 74.8 74.0 77.0 170.0 56.5 225.8 75.3
75 71.5 76.5 84.1 181.2 62.9 232.1 77.4
76 98.0 87.0 76.5 156.3 42.4 261.5 87.2
77 86.8 78.9 89.0 167.6 50.8 254.7 84.9
78 72.0 67.4 91.6 163.8 48.7 231.0 77.0
79 77.1 96.8 68.4 166.4 53.5 242.3 80.8
80 72.5 89.1 92.6 163.0 55.1 254.2 84.7
81 99.6 82.4 75.3 161.3 65.8 257.3 85.8
82 92.5 92.2 87.2 172.6 71.8 271.9 90.6
83 79.9 66.6 88.6 159.3 54.7 235.1 78.4
84 86.3 86.6 82.6 179.9 52.0 255.5 85.2
85 78.7 74.8 79.5 158.5 51.6 233.0 77.7
86 78.2 86.8 85.2 168.8 57.9 250.2 83.4
87 75.7 79.4 87.1 172.3 59.6 242.2 80.7
88 77.2 86.3 90.2 172.7 66.8 253.7 84.6
89 95.2 93.4 69.6 165.6 58.8 258.2 86.1
90 81.6 80.1 72.5 168.6 41.2 234.2 78.1
91 83.0 90.2 94.0 175.7 61.1 267.2 89.1
92 83.9 68.1 91.3 156.3 73.9 243.3 81.1
93 91.9 72.8 87.0 161.7 73.9 251.7 83.9
94 77.9 95.2 89.0 170.6 54.1 262.1 87.4
95 74.1 83.8 90.4 164.4 46.5 248.3 82.8
96 95.4 59.5 65.4 179.0 86.6 220.3 73.4
97 78.5 66.4 91.8 173.4 60.4 236.7 78.9
98 76.2 78.0 80.6 168.6 61.0 234.8 78.3
99 72.1 88.7 85.6 155.9 66.2 246.4 82.1
100 71.7 79.0 81.9 168.2 45.9 232.6 77.5
101 77.4 86.2 90.1 165.5 54.7 253.7 84.6
102 86.9 89.6 81.6 167.2 46.6 258.1 86.0
103 90.9 96.7 87.6 158.5 55.1 275.2 91.7
104 87.7 80.6 81.3 172.0 63.2 249.6 83.2
105 79.1 79.5 76.4 159.7 48.4 235.0 78.3
106 82.5 62.5 92.5 166.2 67.9 237.5 79.2
107 76.4 81.0 89.2 171.1 64.9 246.6 82.2
108 76.3 74.3 96.1 161.7 53.0 246.7 82.2
109 89.1 70.3 84.5 172.7 64.3 243.9 81.3
110 73.9 78.2 91.9 157.5 69.5 244.0 81.3
111 97.6 90.1 97.8 145.5 72.6 285.5 95.2
112 81.3 60.1 82.0 171.7 59.9 223.4 74.5
113 83.7 75.7 74.7 174.7 61.1 234.1 78.0
114 76.1 81.2 82.3 165.7 61.1 239.6 79.9
115 77.4 71.1 82.5 172.0 76.4 231.0 77.0
116 71.5 83.3 85.1 158.8 73.3 239.9 80.0
117 80.5 84.1 96.0 167.0 70.3 260.6 86.9
118 85.4 79.7 81.7 152.5 59.1 246.8 82.3
119 84.6 55.3 86.6 177.4 65.7 226.5 75.5
120 75.7 105.7 82.4 182.9 66.0 263.8 87.9
计算相关矩阵:
cor_matrix <- cor(num_data)
cor_matrix chinese math english height weight total
chinese 1.00000000 -0.14768260 -0.07193383 -0.05882792 -0.07526751 0.43858303
math -0.14768260 1.00000000 -0.06183304 0.02451594 -0.05947660 0.65813324
english -0.07193383 -0.06183304 1.00000000 -0.14474227 0.12703379 0.43501978
height -0.05882792 0.02451594 -0.14474227 1.00000000 0.10953662 -0.09179652
weight -0.07526751 -0.05947660 0.12703379 0.10953662 1.00000000 -0.02399884
total 0.43858303 0.65813324 0.43501978 -0.09179652 -0.02399884 1.00000000
average 0.43862909 0.65812300 0.43494255 -0.09298285 -0.02430803 0.99997867
average
chinese 0.43862909
math 0.65812300
english 0.43494255
height -0.09298285
weight -0.02430803
total 0.99997867
average 1.00000000
8.3 处理缺失值时计算相关
如果数据有 NA,建议写:
cor_matrix <- cor(num_data, use = "complete.obs")或者:
cor_matrix <- cor(num_data, use = "pairwise.complete.obs")含义:
| 参数 | 含义 |
|---|---|
"complete.obs" |
只使用完整行 |
"pairwise.complete.obs" |
每一对变量分别使用非缺失值 |
8.4 使用 corrplot 画相关图
if (requireNamespace("corrplot", quietly = TRUE)) {
corrplot::corrplot(cor_matrix)
} else {
message("未安装 corrplot,因此不绘制相关图。")
}8.5 美化相关图
if (requireNamespace("corrplot", quietly = TRUE)) {
corrplot::corrplot(
cor_matrix,
method = "color",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45,
number.cex = 0.8
)
} else {
message("未安装 corrplot,因此不绘制美化相关图。")
}解释:
| 参数 | 含义 |
|---|---|
method = "color" |
用颜色表示相关大小 |
type = "upper" |
只显示上三角 |
addCoef.col = "black" |
添加相关系数数字 |
tl.col = "black" |
变量名颜色 |
tl.srt = 45 |
变量名旋转 45 度 |
number.cex = 0.8 |
数字大小 |
8.6 圆形相关图
if (requireNamespace("corrplot", quietly = TRUE)) {
corrplot::corrplot(
cor_matrix,
method = "circle",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45
)
} else {
message("未安装 corrplot,因此不绘制圆形相关图。")
}9. 马赛克图
9.1 什么是马赛克图?
马赛克图用于展示两个或多个分类变量之间的关系。
例如:
班级和性别是否有关?
它适合分类变量。
比如:
- 班级 vs 性别;
- 地区 vs 渠道;
- 是否购买 vs 性别;
- 是否及格 vs 班级。
9.2 创建分类变量:是否优秀
先创建一个是否优秀变量:
student <- student %>%
mutate(
excellent = ifelse(average >= 85, "优秀", "非优秀")
)
table(student$class, student$excellent)
非优秀 优秀
一班 29 11
二班 29 11
三班 29 11
9.3 基础马赛克图
基础 R 自带 mosaicplot()。
tab_class_excellent <- table(student$class, student$excellent)
mosaicplot(
tab_class_excellent,
main = "班级与是否优秀的马赛克图",
xlab = "班级",
ylab = "是否优秀",
color = TRUE
)解释:
- 每个矩形的面积表示人数比例;
- 如果某一块面积大,说明该组合人数多;
- 这里的颜色主要用于区分类别组合。
9.4 三个分类变量的马赛克图
例如同时查看:
- 班级;
- 性别;
- 是否优秀。
tab3 <- table(student$class, student$gender, student$excellent)
mosaicplot(
tab3,
main = "班级、性别与是否优秀的马赛克图",
color = TRUE
)解释:
- 该图展示班级、性别和是否优秀三个分类变量的联合分布;
- 每个矩形区域对应一个类别组合;
- 矩形面积越大,表示该组合中的学生人数越多。
9.5 使用 vcd 包画马赛克图,代码展示,不自动执行
vcd 包中的 mosaic() 函数可以绘制功能更丰富的马赛克图。
例如:
- 可以设置
shade = TRUE根据残差着色; - 可以设置
legend = TRUE显示残差图例; - 可以用于分析分类变量组合是否明显偏离独立性假设。
但是在某些中文标签或多维列联表场景下,vcd::mosaic() 在 Knit 时可能出现如下报错:
missing value where TRUE/FALSE needed
为了保证本文顺利 Knit,这里只展示 vcd::mosaic() 代码,不自动执行。
library(vcd)
tab3_vcd <- xtabs(~ class + gender + excellent, data = student)
vcd::mosaic(
tab3_vcd,
shade = TRUE,
legend = TRUE,
direction = c("v", "h", "v"),
main = "班级、性别与是否优秀的马赛克图"
)解释:
| 参数 | 含义 |
|---|---|
shade = TRUE |
根据残差着色 |
legend = TRUE |
显示残差图例 |
direction |
指定切分方向 |
main |
图形标题 |
注意:
mosaicplot(color = TRUE)的颜色主要是区分类别区域;vcd::mosaic(shade = TRUE)的颜色表示残差方向和大小;- 两者统计含义不完全一样。
10. 图形修改与美化
下面集中讲一些常见修改方法。
10.1 修改标题和坐标轴名称
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue") +
labs(
title = "语文成绩与数学成绩的关系",
subtitle = "示例数据:120名学生",
caption = "数据来源:模拟数据",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()10.2 修改颜色
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
scale_color_manual(
values = c(
"一班" = "#E64B35",
"二班" = "#4DBBD5",
"三班" = "#00A087"
)
) +
labs(
title = "手动修改颜色",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()10.3 修改填充色
柱形图、盒形图、小提琴图通常用 fill。
ggplot(student, aes(x = class, y = average, fill = class)) +
geom_boxplot(alpha = 0.7) +
scale_fill_manual(
values = c(
"一班" = "#F8766D",
"二班" = "#7CAE00",
"三班" = "#00BFC4"
)
) +
labs(
title = "手动修改填充颜色",
x = "班级",
y = "平均分"
) +
theme_minimal()10.4 修改点的形状和大小
ggplot(student, aes(x = chinese, y = math, color = class, shape = gender)) +
geom_point(size = 3, alpha = 0.8) +
labs(
title = "修改点的形状和大小",
x = "语文成绩",
y = "数学成绩",
color = "班级",
shape = "性别"
) +
theme_minimal()10.5 修改坐标轴范围
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue") +
scale_x_continuous(limits = c(50, 110)) +
scale_y_continuous(limits = c(50, 110)) +
labs(
title = "修改坐标轴范围",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()也可以用:
ggplot(student, aes(x = chinese, y = math)) +
geom_point(color = "steelblue") +
coord_cartesian(
xlim = c(50, 110),
ylim = c(50, 110)
) +
labs(
title = "使用 coord_cartesian() 修改显示范围",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal()区别:
| 方法 | 特点 |
|---|---|
scale_x_continuous(limits = ...) |
超出范围的数据会被删除 |
coord_cartesian(xlim = ...) |
只是缩放显示区域,不删除数据 |
一般推荐用:
coord_cartesian()10.6 修改主题
p <- ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
labs(
title = "不同主题效果",
x = "语文成绩",
y = "数学成绩",
color = "班级"
)
p + theme_minimal()p + theme_classic()p + theme_bw()p + theme_light()常见主题:
| 主题 | 特点 |
|---|---|
theme_minimal() |
简洁 |
theme_classic() |
经典坐标轴 |
theme_bw() |
黑白主题 |
theme_light() |
浅色网格 |
theme_void() |
去掉坐标轴和背景 |
10.7 修改图例位置
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
labs(
title = "图例放到底部",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal() +
theme(
legend.position = "bottom"
)去掉图例:
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
labs(
title = "去掉图例",
x = "语文成绩",
y = "数学成绩"
) +
theme_minimal() +
theme(
legend.position = "none"
)10.8 修改文字大小
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
labs(
title = "修改文字大小",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal(base_size = 16)更精细地修改:
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
labs(
title = "精细修改文字大小",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 18, face = "bold"),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12),
legend.title = element_text(size = 13),
legend.text = element_text(size = 11)
)10.9 旋转横轴文字
ggplot(student, aes(x = class, y = average, fill = class)) +
geom_boxplot() +
labs(
title = "旋转横轴文字",
x = "班级",
y = "平均分"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)解释:
| 参数 | 含义 |
|---|---|
angle = 45 |
旋转 45 度 |
hjust = 1 |
右对齐 |
10.10 修改图形背景和网格线
ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2) +
labs(
title = "修改背景和网格线",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal() +
theme(
panel.grid.major = element_line(color = "grey80"),
panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "white", color = NA),
plot.background = element_rect(fill = "white", color = NA)
)11. 保存图片
推荐先把图保存成对象。
p_scatter <- ggplot(student, aes(x = chinese, y = math, color = class)) +
geom_point(size = 2, alpha = 0.7) +
labs(
title = "语文成绩与数学成绩的关系",
x = "语文成绩",
y = "数学成绩",
color = "班级"
) +
theme_minimal()
p_scatter保存图片:
ggsave(
filename = "scatter_plot.png",
plot = p_scatter,
width = 6,
height = 4,
dpi = 300
)保存为 PDF:
ggsave(
filename = "scatter_plot.pdf",
plot = p_scatter,
width = 6,
height = 4
)12. 常见错误
12.1 报错:could not find function “ggplot”
原因:没有加载 ggplot2。
解决:
library(ggplot2)12.2 报错:could not find function “ggpairs”
原因:没有安装或没有加载 GGally。
解决:
install.packages("GGally")
library(GGally)或者使用:
GGally::ggpairs(data)12.3 报错:could not find function “corrplot”
原因:没有安装或没有加载 corrplot。
解决:
install.packages("corrplot")
library(corrplot)或者使用:
corrplot::corrplot(cor_matrix)12.4 报错:object ‘x’ not found
原因:代码里用了不存在的变量名。
例如:
ggplot(student, aes(x = x, y = y)) +
geom_point()但 student 里面没有 x 和 y 这两个变量。
解决:
names(student)先查看真实变量名,然后改成真实变量:
ggplot(student, aes(x = chinese, y = math)) +
geom_point()12.5 报错:Discrete value supplied to continuous scale
意思是:
你把分类变量传给了连续型坐标轴或连续型颜色刻度。
例如:
ggplot(student, aes(x = class, y = average)) +
geom_point() +
scale_x_continuous()class 是分类变量,不能用 scale_x_continuous()。
应该用:
scale_x_discrete()或者直接不写。
12.6 vcd::mosaic() 报错:missing value where TRUE/FALSE needed
原因通常是 vcd::mosaic() 在处理多维列联表、中文标签或切分方向时出现兼容性问题。
可能报错:
Error in if (split_vertical[i]) ...:
missing value where TRUE/FALSE needed
解决方法:
- 使用基础 R 的
mosaicplot(); - 或者在
vcd::mosaic()中明确设置direction; - 如果是在 R Markdown 中 Knit,建议先把
vcd::mosaic()设置为eval=FALSE; - 等确认控制台能正常运行后,再考虑打开执行。
示例:
vcd::mosaic(
tab,
shade = TRUE,
legend = TRUE,
direction = c("v", "h")
)13. 小练习
创建一份销售数据:
set.seed(456)
sales <- data.frame(
id = 1:150,
region = sample(c("华东", "华北", "华南"), 150, replace = TRUE),
channel = sample(c("线上", "线下"), 150, replace = TRUE),
category = sample(c("食品", "服装", "电子"), 150, replace = TRUE),
price = round(rnorm(150, mean = 100, sd = 20), 1),
quantity = sample(1:10, 150, replace = TRUE)
)
sales$amount <- round(sales$price * sales$quantity, 1)
sales id region channel category price quantity amount
1 1 华东 线上 电子 108.1 4 432.4
2 2 华东 线下 服装 134.8 8 1078.4
3 3 华南 线上 服装 101.2 3 303.6
4 4 华北 线下 电子 112.1 7 784.7
5 5 华东 线下 服装 96.8 6 580.8
6 6 华南 线上 服装 88.7 7 620.9
7 7 华东 线上 食品 86.0 9 774.0
8 8 华北 线上 食品 92.7 1 92.7
9 9 华南 线上 电子 96.2 9 865.8
10 10 华北 线上 服装 73.5 7 514.5
11 11 华东 线上 电子 109.3 2 218.6
12 12 华南 线上 食品 133.7 7 935.9
13 13 华北 线下 服装 116.0 7 812.0
14 14 华南 线下 电子 118.1 2 236.2
15 15 华南 线上 食品 120.2 2 240.4
16 16 华南 线下 食品 120.1 4 480.4
17 17 华北 线上 服装 123.6 3 370.8
18 18 华北 线上 电子 105.9 7 741.3
19 19 华东 线下 服装 117.3 3 351.9
20 20 华东 线上 服装 74.8 1 74.8
21 21 华北 线上 电子 77.7 3 233.1
22 22 华南 线上 电子 133.5 2 267.0
23 23 华东 线上 电子 80.7 8 645.6
24 24 华东 线上 电子 127.6 2 255.2
25 25 华北 线下 食品 138.1 3 414.3
26 26 华东 线下 服装 118.7 3 356.1
27 27 华东 线下 食品 96.1 8 768.8
28 28 华北 线下 电子 119.9 3 359.7
29 29 华北 线下 服装 134.8 4 539.2
30 30 华南 线下 服装 128.4 9 1155.6
31 31 华北 线上 食品 90.2 3 270.6
32 32 华南 线下 食品 120.0 9 1080.0
33 33 华东 线下 电子 94.3 7 660.1
34 34 华北 线上 电子 98.2 6 589.2
35 35 华东 线上 电子 133.5 4 534.0
36 36 华南 线下 食品 123.1 2 246.2
37 37 华北 线下 服装 116.7 6 700.2
38 38 华南 线上 电子 128.6 4 514.4
39 39 华北 线下 服装 107.9 10 1079.0
40 40 华北 线下 电子 84.2 8 673.6
41 41 华南 线下 电子 116.6 4 466.4
42 42 华北 线上 电子 94.0 5 470.0
43 43 华南 线上 服装 101.1 7 707.7
44 44 华南 线上 服装 115.0 3 345.0
45 45 华东 线下 服装 84.2 2 168.4
46 46 华东 线上 电子 130.1 5 650.5
47 47 华东 线上 电子 89.4 6 536.4
48 48 华北 线上 服装 104.9 6 629.4
49 49 华北 线上 电子 103.7 1 103.7
50 50 华南 线下 食品 125.9 3 377.7
51 51 华南 线上 服装 127.0 1 127.0
52 52 华北 线下 食品 63.6 2 127.2
53 53 华北 线上 食品 79.7 7 557.9
54 54 华东 线上 电子 115.5 3 346.5
55 55 华南 线上 食品 95.1 8 760.8
56 56 华南 线下 服装 84.7 5 423.5
57 57 华北 线上 食品 123.7 2 247.4
58 58 华南 线下 服装 111.4 8 891.2
59 59 华南 线下 服装 105.0 7 735.0
60 60 华东 线上 食品 73.3 5 366.5
61 61 华南 线上 服装 77.0 10 770.0
62 62 华东 线上 服装 149.1 7 1043.7
63 63 华北 线上 电子 103.7 9 933.3
64 64 华东 线下 电子 91.2 3 273.6
65 65 华东 线下 服装 98.8 3 296.4
66 66 华北 线下 食品 146.4 6 878.4
67 67 华南 线下 食品 112.9 10 1129.0
68 68 华南 线下 服装 106.4 4 425.6
69 69 华东 线下 食品 78.8 6 472.8
70 70 华东 线下 服装 62.8 1 62.8
71 71 华北 线下 食品 105.6 8 844.8
72 72 华北 线上 电子 94.6 5 473.0
73 73 华南 线上 食品 112.6 10 1126.0
74 74 华东 线下 电子 59.0 2 118.0
75 75 华北 线上 电子 107.7 9 969.3
76 76 华南 线上 食品 118.8 7 831.6
77 77 华东 线上 服装 119.2 10 1192.0
78 78 华南 线上 服装 74.1 8 592.8
79 79 华北 线上 服装 104.0 4 416.0
80 80 华东 线下 服装 127.9 10 1279.0
81 81 华北 线下 食品 91.1 8 728.8
82 82 华北 线上 食品 93.1 4 372.4
83 83 华南 线上 食品 73.2 10 732.0
84 84 华东 线上 食品 106.5 2 213.0
85 85 华北 线上 电子 106.9 7 748.3
86 86 华南 线上 电子 121.8 7 852.6
87 87 华南 线下 食品 78.3 4 313.2
88 88 华北 线下 食品 123.0 2 246.0
89 89 华东 线下 服装 75.4 10 754.0
90 90 华东 线上 电子 126.9 1 126.9
91 91 华东 线下 服装 80.6 6 483.6
92 92 华东 线下 服装 138.1 10 1381.0
93 93 华东 线下 电子 106.7 5 533.5
94 94 华东 线上 食品 72.2 5 361.0
95 95 华东 线上 服装 91.4 3 274.2
96 96 华南 线上 电子 99.1 10 991.0
97 97 华北 线下 食品 94.3 4 377.2
98 98 华南 线上 服装 99.0 9 891.0
99 99 华北 线上 服装 78.2 2 156.4
100 100 华南 线上 食品 88.6 8 708.8
101 101 华南 线下 电子 122.1 8 976.8
102 102 华东 线上 食品 125.1 4 500.4
103 103 华东 线上 服装 70.2 9 631.8
104 104 华南 线上 服装 126.9 5 634.5
105 105 华东 线上 食品 101.5 5 507.5
106 106 华南 线下 电子 67.8 3 203.4
107 107 华东 线上 服装 109.8 7 768.6
108 108 华东 线下 服装 103.0 3 309.0
109 109 华东 线下 电子 110.4 6 662.4
110 110 华东 线下 食品 90.5 1 90.5
111 111 华北 线上 服装 102.7 9 924.3
112 112 华东 线下 电子 102.8 7 719.6
113 113 华东 线下 食品 113.0 1 113.0
114 114 华北 线下 电子 105.6 5 528.0
115 115 华北 线下 食品 100.0 6 600.0
116 116 华北 线下 服装 82.4 10 824.0
117 117 华东 线上 服装 53.5 2 107.0
118 118 华北 线上 服装 124.0 3 372.0
119 119 华北 线上 食品 90.3 3 270.9
120 120 华南 线上 食品 110.2 9 991.8
121 121 华东 线下 服装 105.1 3 315.3
122 122 华东 线上 食品 74.1 8 592.8
123 123 华东 线下 食品 110.0 3 330.0
124 124 华北 线下 食品 121.0 6 726.0
125 125 华南 线下 服装 95.1 3 285.3
126 126 华东 线下 电子 71.2 10 712.0
127 127 华东 线上 电子 81.9 4 327.6
128 128 华东 线下 食品 117.2 5 586.0
129 129 华东 线下 食品 83.6 3 250.8
130 130 华东 线下 服装 70.6 10 706.0
131 131 华北 线上 电子 103.6 9 932.4
132 132 华东 线下 食品 102.9 7 720.3
133 133 华南 线下 服装 78.9 2 157.8
134 134 华北 线上 电子 75.5 5 377.5
135 135 华东 线上 电子 87.2 7 610.4
136 136 华南 线下 电子 104.5 5 522.5
137 137 华北 线下 食品 106.3 4 425.2
138 138 华东 线下 电子 94.1 9 846.9
139 139 华北 线上 服装 66.7 5 333.5
140 140 华南 线上 食品 136.2 3 408.6
141 141 华东 线上 电子 119.1 4 476.4
142 142 华东 线上 电子 82.1 7 574.7
143 143 华南 线下 食品 75.7 9 681.3
144 144 华东 线上 电子 110.1 9 990.9
145 145 华北 线下 电子 117.8 5 589.0
146 146 华南 线上 电子 90.9 4 363.6
147 147 华东 线下 电子 105.8 2 211.6
148 148 华北 线上 食品 94.8 3 284.4
149 149 华东 线下 服装 109.5 7 766.5
150 150 华北 线下 电子 95.7 4 382.8
请完成:
- 画价格和销售额的散点图,并标注销售额最高的 5 个订单;
- 画气泡图:横轴价格,纵轴销售额,气泡大小为数量,颜色为地区;
- 画价格、数量、销售额的散点图矩阵;
- 画分组散点图:颜色为地区,形状为渠道;
- 计算价格、数量、销售额的相关矩阵并画相关图;
- 画地区和渠道的马赛克图;
- 修改图形标题、颜色、主题和图例位置。
14. 小练习参考答案
14.1 标注销售额最高的 5 个订单
top5_sales <- sales %>%
arrange(desc(amount)) %>%
slice(1:5)
top5_sales id region channel category price quantity amount
1 92 华东 线下 服装 138.1 10 1381.0
2 80 华东 线下 服装 127.9 10 1279.0
3 77 华东 线上 服装 119.2 10 1192.0
4 30 华南 线下 服装 128.4 9 1155.6
5 67 华南 线下 食品 112.9 10 1129.0
ggplot(sales, aes(x = price, y = amount)) +
geom_point(color = "grey50", alpha = 0.7) +
geom_point(
data = top5_sales,
color = "red",
size = 3
) +
geom_label(
data = top5_sales,
aes(label = paste0("ID=", id)),
fill = "yellow",
color = "red",
size = 3
) +
labs(
title = "价格与销售额散点图:标注最高销售额订单",
x = "价格",
y = "销售额"
) +
theme_minimal()14.2 气泡图
ggplot(sales, aes(x = price, y = amount, size = quantity, color = region)) +
geom_point(alpha = 0.6) +
scale_size_continuous(range = c(2, 10)) +
labs(
title = "气泡图:价格、销售额与购买数量",
x = "价格",
y = "销售额",
size = "数量",
color = "地区"
) +
theme_minimal()14.3 散点图矩阵
if (requireNamespace("GGally", quietly = TRUE)) {
GGally::ggpairs(
sales,
columns = c("price", "quantity", "amount")
)
} else {
message("未安装 GGally,因此不绘制销售数据散点图矩阵。")
}分组散点图矩阵:
if (requireNamespace("GGally", quietly = TRUE)) {
GGally::ggpairs(
sales,
columns = c("price", "quantity", "amount"),
aes(color = region, alpha = 0.6)
)
} else {
message("未安装 GGally,因此不绘制销售数据分组散点图矩阵。")
}14.4 分组散点图
ggplot(sales, aes(x = price, y = amount, color = region, shape = channel)) +
geom_point(size = 2.5, alpha = 0.8) +
labs(
title = "价格与销售额分组散点图",
x = "价格",
y = "销售额",
color = "地区",
shape = "渠道"
) +
theme_minimal()14.5 相关图
sales_num <- sales %>%
select(price, quantity, amount)
sales_cor <- cor(sales_num)
sales_cor price quantity amount
price 1.00000000 -0.06722087 0.2881969
quantity -0.06722087 1.00000000 0.9157241
amount 0.28819690 0.91572410 1.0000000
if (requireNamespace("corrplot", quietly = TRUE)) {
corrplot::corrplot(
sales_cor,
method = "color",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45
)
} else {
message("未安装 corrplot,因此不绘制销售数据相关图。")
}14.6 马赛克图
基础 R 写法:
tab_region_channel <- table(sales$region, sales$channel)
mosaicplot(
tab_region_channel,
main = "地区与渠道的马赛克图",
xlab = "地区",
ylab = "渠道",
color = TRUE
)解释:
- 该图展示地区和渠道两个分类变量的联合分布;
- 矩形面积越大,表示该地区与该渠道组合下的订单数越多。
14.7 使用 vcd 绘制马赛克图,代码展示,不自动执行
如果想使用 vcd::mosaic(),可以参考下面代码。
为避免 Knit 报错,这里设置为 eval=FALSE。
library(vcd)
vcd::mosaic(
tab_region_channel,
shade = TRUE,
legend = TRUE,
direction = c("v", "h"),
main = "地区与渠道的马赛克图"
)说明:
shade = TRUE表示根据残差着色;legend = TRUE表示显示残差图例;direction = c("v", "h")指定二维表的切分方向;- 如果控制台运行正常,可以再考虑让 R Markdown 执行该代码。
14.8 图形修改示例
ggplot(sales, aes(x = price, y = amount, color = region, shape = channel)) +
geom_point(size = 3, alpha = 0.75) +
scale_color_manual(
values = c(
"华东" = "#E64B35",
"华北" = "#4DBBD5",
"华南" = "#00A087"
)
) +
labs(
title = "价格与销售额关系",
subtitle = "颜色表示地区,形状表示渠道",
caption = "数据来源:模拟销售数据",
x = "商品价格",
y = "销售额",
color = "地区",
shape = "渠道"
) +
theme_classic(base_size = 14) +
theme(
legend.position = "bottom",
plot.title = element_text(face = "bold", size = 18),
plot.subtitle = element_text(size = 13),
axis.title = element_text(size = 14)
)15. 本节核心代码总结
下面是模板代码,只展示,不运行。
# 加载包
library(ggplot2)
library(dplyr)
# 1. 散点图 + 标注
ggplot(df, aes(x = x_var, y = y_var)) +
geom_point() +
geom_text(aes(label = label_var))
# 2. 只标注部分点
label_df <- df %>%
filter(condition)
ggplot(df, aes(x = x_var, y = y_var)) +
geom_point() +
geom_point(data = label_df, color = "red") +
geom_label(data = label_df, aes(label = label_var))
# 3. 添加参考线
ggplot(df, aes(x = x_var, y = y_var)) +
geom_point() +
geom_hline(yintercept = 80, linetype = "dashed") +
geom_vline(xintercept = 80, linetype = "dashed")
# 4. 添加说明文字
ggplot(df, aes(x = x_var, y = y_var)) +
geom_point() +
annotate("text", x = 10, y = 20, label = "说明文字")
# 5. 气泡图
ggplot(df, aes(x = x_var, y = y_var, size = size_var, color = group_var)) +
geom_point(alpha = 0.6) +
scale_size_continuous(range = c(2, 10))
# 6. 分组散点图
ggplot(df, aes(x = x_var, y = y_var, color = group_var, shape = type_var)) +
geom_point()
# 7. 分组散点图 + 趋势线
ggplot(df, aes(x = x_var, y = y_var, color = group_var)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE)
# 8. 分面散点图
ggplot(df, aes(x = x_var, y = y_var, color = group_var)) +
geom_point() +
facet_wrap(~ facet_var)
# 9. 散点图矩阵
GGally::ggpairs(
df,
columns = c("x1", "x2", "x3")
)
# 10. 分组散点图矩阵
GGally::ggpairs(
df,
columns = c("x1", "x2", "x3"),
aes(color = group_var, alpha = 0.6)
)
# 11. 相关矩阵
num_df <- df %>%
select(x1, x2, x3)
cor_matrix <- cor(num_df, use = "complete.obs")
# 12. 相关图
corrplot::corrplot(
cor_matrix,
method = "color",
type = "upper",
addCoef.col = "black"
)
# 13. 基础马赛克图
tab <- table(df$group1, df$group2)
mosaicplot(
tab,
main = "马赛克图",
color = TRUE
)
# 14. vcd 马赛克图
# 注意:在某些中文标签或多维列联表场景下可能需要额外设置。
# 建议先在控制台单独测试,再放入 R Markdown 中执行。
library(vcd)
vcd::mosaic(
tab,
shade = TRUE,
legend = TRUE,
direction = c("v", "h"),
main = "vcd 马赛克图"
)
# 15. 修改标题
ggplot(df, aes(x = x_var, y = y_var)) +
geom_point() +
labs(
title = "标题",
subtitle = "副标题",
caption = "注释",
x = "横轴名称",
y = "纵轴名称"
)
# 16. 修改颜色
ggplot(df, aes(x = x_var, y = y_var, color = group_var)) +
geom_point() +
scale_color_manual(values = c("A" = "red", "B" = "blue"))
# 17. 修改主题和图例
ggplot(df, aes(x = x_var, y = y_var, color = group_var)) +
geom_point() +
theme_minimal() +
theme(
legend.position = "bottom",
plot.title = element_text(size = 18, face = "bold")
)
# 18. 保存图片
ggsave(
filename = "plot.png",
plot = p,
width = 6,
height = 4,
dpi = 300
)16. 一句话总结
本节最常用代码如下:
geom_text()
geom_label()
annotate()用于给图添加文字标注。
ggplot(df, aes(x, y, size = z)) +
geom_point()用于画气泡图。
GGally::ggpairs()用于画散点图矩阵。
corrplot::corrplot()用于画相关图。
mosaicplot()用于绘制基础马赛克图。
vcd::mosaic()也可以绘制更丰富的马赛克图,并支持残差着色;但在某些中文标签或多维表情况下可能需要额外设置。为了保证本文 Knit 稳定,正文中 vcd::mosaic() 只作为代码示例展示,不自动执行。
图形修改最常用的是:
labs()
theme()
scale_color_manual()
scale_fill_manual()
theme_minimal()
theme_classic()