创建表
# 学生信息
student <- tribble(
~学号, ~姓名, ~生日, ~性别,
"01", "赵雷", "1990-01-01", "男",
"02", "钱电", "1990-12-21", "男",
"03", "孙风", "1990-05-20", "男",
"04", "李云", "1990-08-06", "男",
"05", "周梅", "1991-12-01", "女",
"06", "吴兰", "1992-03-01", "女",
"07", "郑竹", "1989-07-01", "女",
"08", "王菊", "1990-01-20", "女"
)
student
# A tibble: 8 × 4
学号 姓名 生日 性别
<chr> <chr> <chr> <chr>
1 01 赵雷 1990-01-01 男
2 02 钱电 1990-12-21 男
3 03 孙风 1990-05-20 男
4 04 李云 1990-08-06 男
5 05 周梅 1991-12-01 女
6 06 吴兰 1992-03-01 女
7 07 郑竹 1989-07-01 女
8 08 王菊 1990-01-20 女
# 分数信息
score <- tribble(
~学号, ~课程编号, ~成绩,
"01", "01", 80,
"01", "02", 90,
"01", "03", 99,
"02", "01", 70,
"02", "02", 60,
"02", "03", 80,
"03", "01", 80,
"03", "02", 80,
"03", "03", 80,
"04", "01", 50,
"04", "02", 30,
"04", "03", 20,
"05", "01", 76,
"05", "02", 87,
"06", "01", 31,
"06", "03", 34,
"07", "02", 89,
"07", "03", 98
)
score
# A tibble: 18 × 3
学号 课程编号 成绩
<chr> <chr> <dbl>
1 01 01 80
2 01 02 90
3 01 03 99
4 02 01 70
5 02 02 60
6 02 03 80
7 03 01 80
8 03 02 80
9 03 03 80
10 04 01 50
11 04 02 30
12 04 03 20
13 05 01 76
14 05 02 87
15 06 01 31
16 06 03 34
17 07 02 89
18 07 03 98
# 课程信息
course <- tribble(
~课程编号, ~课程名称, ~教师编号,
"01", "语文", "02",
"02", "数学", "01",
"03", "英语", "03"
)
course
# A tibble: 3 × 3
课程编号 课程名称 教师编号
<chr> <chr> <chr>
1 01 语文 02
2 02 数学 01
3 03 英语 03
# 教师信息
teacher <- tribble(
~教师编号, ~教师姓名,
"01", "张三",
"02", "李四",
"03", "王五"
)
teacher
# A tibble: 3 × 2
教师编号 教师姓名
<chr> <chr>
1 01 张三
2 02 李四
3 03 王五
1 查询”01”课程比”02”课程成绩高的学生的信息及课程分数
# 长表变宽表
score_1 <- score %>%
pivot_wider(
names_from = 课程编号, values_from = 成绩,
names_prefix = "课程"
)
score_1
# A tibble: 7 × 4
学号 课程01 课程02 课程03
<chr> <dbl> <dbl> <dbl>
1 01 80 90 99
2 02 70 60 80
3 03 80 80 80
4 04 50 30 20
5 05 76 87 NA
6 06 31 NA 34
7 07 NA 89 98
# A tibble: 2 × 7
学号 课程01 课程02 课程03 姓名 生日 性别
<chr> <dbl> <dbl> <dbl> <chr> <chr> <chr>
1 02 70 60 80 钱电 1990-12-21 男
2 04 50 30 20 李云 1990-08-06 男
2 查询”01”课程比”02”课程成绩低的学生的信息及课程分数
3 查询平均成绩大于等于60分的学生学号、姓名和平均成绩
score_mean <- score %>%
group_by(学号) %>%
summarise(平均成绩 = mean(成绩)) %>%
# 以上两步可简写为:
# summarise(平均成绩 = mean(成绩), .by = 学号)
filter(平均成绩 >= 60)
score_mean
# A tibble: 5 × 2
学号 平均成绩
<chr> <dbl>
1 01 89.7
2 02 70
3 03 80
4 05 81.5
5 07 93.5
# A tibble: 5 × 5
学号 平均成绩 姓名 生日 性别
<chr> <dbl> <chr> <chr> <chr>
1 01 89.7 赵雷 1990-01-01 男
2 02 70 钱电 1990-12-21 男
3 03 80 孙风 1990-05-20 男
4 05 81.5 周梅 1991-12-01 女
5 07 93.5 郑竹 1989-07-01 女
4 查询平均成绩小于60分的学生的学号和姓名和平均成绩(包括有成绩的和无成绩的)
# 不考虑无成绩的
score %>%
summarise(平均成绩 = mean(成绩), .by = 学号) %>%
filter(平均成绩 < 60) %>%
left_join(student, by = "学号") %>%
select(学号, 姓名, 平均成绩)
# A tibble: 2 × 3
学号 姓名 平均成绩
<chr> <chr> <dbl>
1 04 李云 33.3
2 06 吴兰 32.5
# 考虑所有学生(包括无成绩的)
student %>%
left_join(score, by = "学号") %>%
replace_na(list(成绩 = 0)) %>%
summarise(平均成绩 = mean(成绩), .by = c(学号, 姓名)) %>%
filter(平均成绩 < 60)
# A tibble: 3 × 3
学号 姓名 平均成绩
<chr> <chr> <dbl>
1 04 李云 33.3
2 06 吴兰 32.5
3 08 王菊 0
5 查询所有学生的学号、姓名、选课总数、所有课程的总成绩
student %>%
left_join(score, by = "学号") %>%
mutate(成绩 = replace_na(成绩, 0)) %>%
summarise(
选课总数 = n_distinct(课程编号),
总成绩 = sum(成绩),
.by = c(学号, 姓名)
)
# A tibble: 8 × 4
学号 姓名 选课总数 总成绩
<chr> <chr> <int> <dbl>
1 01 赵雷 3 269
2 02 钱电 3 210
3 03 孙风 3 240
4 04 李云 3 100
5 05 周梅 2 163
6 06 吴兰 2 65
7 07 郑竹 2 187
8 08 王菊 1 0
6 查询”李”姓老师的数量
7 查询学过张三老师教授课程的学生信息
teacher %>%
left_join(course, by = "教师编号") %>%
left_join(score, by = "课程编号") %>%
filter(教师姓名 == "张三") %>%
left_join(student, by = "学号") %>%
select(学号, 姓名, 课程编号, 课程名称)
# A tibble: 6 × 4
学号 姓名 课程编号 课程名称
<chr> <chr> <chr> <chr>
1 01 赵雷 02 数学
2 02 钱电 02 数学
3 03 孙风 02 数学
4 04 李云 02 数学
5 05 周梅 02 数学
6 07 郑竹 02 数学
# 或使用半连接
# semi_join(student, ., by = "学号")
8 找出没有学过张三老师教授课程的学生信息
9 查询同时学过”01”和”02”课程的学生信息
10 查询学过”01”课程,但没有学过”02”“课程的学生信息
11 查询没有学完全部课程的学生信息
course %>%
left_join(score, by = "课程编号") %>%
select(-c(课程编号, 教师编号)) %>%
pivot_wider(names_from = 课程名称, values_from = 成绩) %>%
right_join(student, by = "学号") %>%
filter(if_any(2:4, is.na)) %>%
select(-c(2:4))
# A tibble: 4 × 4
学号 姓名 生日 性别
<chr> <chr> <chr> <chr>
1 05 周梅 1991-12-01 女
2 06 吴兰 1992-03-01 女
3 07 郑竹 1989-07-01 女
4 08 王菊 1990-01-20 女
12 查询至少有一门课与学生”01”所学课程相同的学生信息
score %>%
filter(学号 == "01") %>%
semi_join(score, ., by = "课程编号") %>%
semi_join(student, ., by = "学号")
# A tibble: 7 × 4
学号 姓名 生日 性别
<chr> <chr> <chr> <chr>
1 01 赵雷 1990-01-01 男
2 02 钱电 1990-12-21 男
3 03 孙风 1990-05-20 男
4 04 李云 1990-08-06 男
5 05 周梅 1991-12-01 女
6 06 吴兰 1992-03-01 女
7 07 郑竹 1989-07-01 女
13 查询与学生”01”学习的课程完全相同的学生信息
解题思路:
- 先将成绩表按学号分组,然后将每组的课程编号合并成一个字符串,作为新的一列。
- 然后将每组的课程编号字符串与”01”的课程编号字符串进行比较,如果相同,则保留该组数据。
- 最后将该组数据与学生信息表进行半连接,得到结果。
14 查询两门及以上不及格课程的学生学号,姓名及其平均成绩
score %>%
pivot_wider(
names_from = 课程编号, values_from = 成绩,
names_prefix = "课程"
) %>%
filter(
pmap_lgl(
.[-1],
\(...) sum(c(...) < 60, na.rm = TRUE) >= 2
)
) %>%
mutate(
平均成绩 = pmap_dbl(.[-1], \(...) mean(c(...), na.rm = TRUE))
) %>%
left_join(student, by = "学号") %>%
select(学号, 姓名, 平均成绩)
# A tibble: 2 × 3
学号 姓名 平均成绩
<chr> <chr> <dbl>
1 04 李云 33.3
2 06 吴兰 32.5
-
pmap_dbl(df, \(...) mean(c(...), na.rm = TRUE))
可以理解为是pmap_**()
系列函数行化操作数据一个固定搭配。
15 检索”01”课程分数小于60,按分数降序排列的学生信息
16 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
score %>%
pivot_wider(
names_from = 课程编号, values_from = 成绩, names_prefix = "课程"
) %>%
mutate(平均成绩 = pmap_dbl(.[-1], \(...) mean(c(...), na.rm = TRUE))) %>%
left_join(student, by = "学号") %>%
arrange(desc(平均成绩)) %>%
select(学号, 姓名, 性别, everything(), -生日)
# A tibble: 7 × 7
学号 姓名 性别 课程01 课程02 课程03 平均成绩
<chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 07 郑竹 女 NA 89 98 93.5
2 01 赵雷 男 80 90 99 89.7
3 05 周梅 女 76 87 NA 81.5
4 03 孙风 男 80 80 80 80
5 02 钱电 男 70 60 80 70
6 04 李云 男 50 30 20 33.3
7 06 吴兰 女 31 NA 34 32.5
17 查询各科成绩最高分、最低分和平均分,以如下形式显示:
课程编号,课程名称,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
注:及格: >=60,中等为: 70-80,优良为: 80-90,优秀为: >=90
score %>%
summarise(
最高分 = max(成绩), 最低分 = min(成绩), 平均分 = mean(成绩),
及格率 = paste0(round(mean(成绩 >= 60) * 100, 2), "%"), # 转换为百分数
中等率 = mean(70 <= 成绩 & 成绩 < 80),
优良率 = mean(80 <= 成绩 & 成绩 < 90), 优秀率 = mean(90 <= 成绩),
.by = 课程编号
) %>%
left_join(course, by = "课程编号") %>%
# 将“课程名称”列移动到“课程编号”列之后
relocate(课程名称, .after = 课程编号) %>%
select(-教师编号)
# A tibble: 3 × 9
课程编号 课程名称 最高分 最低分 平均分 及格率 中等率 优良率 优秀率
<chr> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
1 01 语文 80 31 64.5 66.67% 0.333 0.333 0
2 02 数学 90 30 72.7 83.33% 0 0.5 0.167
3 03 英语 99 20 68.5 66.67% 0 0.333 0.333
18 按照各科成绩进行排序,并且显示排名
score %>%
group_by(课程编号) %>%
# 使用mutate函数添加一个新列“排名”,通过min_rank函数根据“成绩”列的负值进行排名
mutate(排名 = min_rank(-成绩)) %>%
arrange(课程编号, 排名)
# A tibble: 18 × 4
# Groups: 课程编号 [3]
学号 课程编号 成绩 排名
<chr> <chr> <dbl> <int>
1 01 01 80 1
2 03 01 80 1
3 05 01 76 3
4 02 01 70 4
5 04 01 50 5
6 06 01 31 6
7 01 02 90 1
8 07 02 89 2
9 05 02 87 3
10 03 02 80 4
11 02 02 60 5
12 04 02 30 6
13 01 03 99 1
14 07 03 98 2
15 02 03 80 3
16 03 03 80 3
17 06 03 34 5
18 04 03 20 6
19 查询学生的总成绩,并进行排名
score %>%
summarise(总成绩 = sum(成绩), .by = 学号) %>%
left_join(student, by = "学号") %>%
mutate(排名 = min_rank(-总成绩)) %>%
arrange(排名) %>%
relocate(where(is.numeric), .after = 性别)
# A tibble: 7 × 6
学号 姓名 生日 性别 总成绩 排名
<chr> <chr> <chr> <chr> <dbl> <int>
1 01 赵雷 1990-01-01 男 269 1
2 03 孙风 1990-05-20 男 240 2
3 02 钱电 1990-12-21 男 210 3
4 07 郑竹 1989-07-01 女 187 4
5 05 周梅 1991-12-01 女 163 5
6 04 李云 1990-08-06 男 100 6
7 06 吴兰 1992-03-01 女 65 7
20 查询不同老师所教不同课程平均分从高到低显示
21 查询所有课程的成绩第2至3名的学生信息及该课程成绩
- 分组修改:按课程分组,计算成绩排名,则为每门课程的成绩排名
- 筛选行:排名为 2 或 3
- 排序行:按课程、排名排序让结果更整齐
- 左连接:学生信息,需要连接学生表进来
- 选择列:删除不想显示的列
score %>%
mutate(排名 = min_rank(-成绩), .by = 课程编号) %>%
filter(排名 %in% c(2, 3)) %>%
arrange(课程编号, 排名) %>%
left_join(student, by = "学号") %>%
select(-c(排名, 课程编号))
# A tibble: 6 × 5
学号 成绩 姓名 生日 性别
<chr> <dbl> <chr> <chr> <chr>
1 05 76 周梅 1991-12-01 女
2 07 89 郑竹 1989-07-01 女
3 05 87 周梅 1991-12-01 女
4 07 98 郑竹 1989-07-01 女
5 02 80 钱电 1990-12-21 男
6 03 80 孙风 1990-05-20 男
22 统计各科成绩各分数段人数:课程编号,课程名称,[85,100],[70,85),[60,70),[60)及所占百分比
score %>%
group_by(课程编号) %>%
mutate(
分数段 = cut(成绩,
breaks = c(0, 60, 70, 85, 100, 101), right = FALSE,
# labels = c("不及格", "60-70", "70-85", "85-100", "优秀")
)
) %>%
count(课程编号, 分数段) %>%
mutate(百分比 = scales::percent(n / sum(n), accuracy = 0.01)) %>%
left_join(course, by = "课程编号") %>%
select(-教师编号)
# A tibble: 9 × 5
# Groups: 课程编号 [3]
课程编号 分数段 n 百分比 课程名称
<chr> <fct> <int> <chr> <chr>
1 01 [0,60) 2 33.33% 语文
2 01 [70,85) 4 66.67% 语文
3 02 [0,60) 1 16.67% 数学
4 02 [60,70) 1 16.67% 数学
5 02 [70,85) 1 16.67% 数学
6 02 [85,100) 3 50.00% 数学
7 03 [0,60) 2 33.33% 英语
8 03 [70,85) 2 33.33% 英语
9 03 [85,100) 2 33.33% 英语
23 查询学生的平均成绩及名次
score %>%
summarise(平均成绩 = mean(成绩), .by = 学号) %>%
mutate(名次 = min_rank(-平均成绩)) %>%
arrange(名次) %>%
left_join(student, by = "学号")
# A tibble: 7 × 6
学号 平均成绩 名次 姓名 生日 性别
<chr> <dbl> <int> <chr> <chr> <chr>
1 07 93.5 1 郑竹 1989-07-01 女
2 01 89.7 2 赵雷 1990-01-01 男
3 05 81.5 3 周梅 1991-12-01 女
4 03 80 4 孙风 1990-05-20 男
5 02 70 5 钱电 1990-12-21 男
6 04 33.3 6 李云 1990-08-06 男
7 06 32.5 7 吴兰 1992-03-01 女
24 查询各科成绩前三名的记录
score %>%
group_by(课程编号) %>%
slice_head(n = 3)
# A tibble: 9 × 3
# Groups: 课程编号 [3]
学号 课程编号 成绩
<chr> <chr> <dbl>
1 01 01 80
2 02 01 70
3 03 01 80
4 01 02 90
5 02 02 60
6 03 02 80
7 01 03 99
8 02 03 80
9 03 03 80
# A tibble: 10 × 6
学号 课程编号 成绩 姓名 生日 性别
<chr> <chr> <dbl> <chr> <chr> <chr>
1 01 01 80 赵雷 1990-01-01 男
2 03 01 80 孙风 1990-05-20 男
3 05 01 76 周梅 1991-12-01 女
4 01 02 90 赵雷 1990-01-01 男
5 07 02 89 郑竹 1989-07-01 女
6 05 02 87 周梅 1991-12-01 女
7 01 03 99 赵雷 1990-01-01 男
8 07 03 98 郑竹 1989-07-01 女
9 02 03 80 钱电 1990-12-21 男
10 03 03 80 孙风 1990-05-20 男
25 查询每门课被选修的学生数
26 查询出只有两门课程的全部学生的学号和姓名
27 查询男女生人数
28 查询名字中含有风字的学生信息
student %>%
filter(str_detect(姓名, "风"))
# A tibble: 1 × 4
学号 姓名 生日 性别
<chr> <chr> <chr> <chr>
1 03 孙风 1990-05-20 男
29 查询同姓名同性别的学生名单,并统计同姓名人数
- 按姓名、性别分组计数,数量大于1说明有重复。
- 选出姓名重复的行,有几行就说明有几个同姓名。
30 查询1990年出生的学生信息
31 计算每门课程的平均成绩,并按降序排列;若平均成绩相同,按课程编号升序排列
32 查询平均成绩>=85分的学生学号、姓名和平均成绩
33 查询课程名称为数学,且分数低于60的学生姓名和分数
34 查询所有学生的课程及分数情况
score %>%
left_join(course, by = "课程编号") %>%
left_join(student, by = "学号") %>%
select(-c(学号, 课程编号, 教师编号, 生日, 性别)) %>%
pivot_wider(names_from = 课程名称, values_from = 成绩) %>%
mutate(总分 = pmap_dbl(.[-1], \(...) sum(c(...), na.rm = TRUE)))
# A tibble: 7 × 5
姓名 语文 数学 英语 总分
<chr> <dbl> <dbl> <dbl> <dbl>
1 赵雷 80 90 99 269
2 钱电 70 60 80 210
3 孙风 80 80 80 240
4 李云 50 30 20 100
5 周梅 76 87 NA 163
6 吴兰 31 NA 34 65
7 郑竹 NA 89 98 187
35 查询任何一门课程成绩都在70分以上的姓名、课程名称和分数
score %>%
left_join(course, by = "课程编号") %>%
select(-c(课程编号, 教师编号)) %>%
pivot_wider(names_from = 课程名称, values_from = 成绩) %>%
left_join(student, by = "学号") %>%
# 过滤数据框,保留第二到第四列中所有值大于70的行
filter(pmap_lgl(.[2:4], \(...) all(na.omit(c(...)) > 70))) %>%
select(学号, 姓名, 语文, 数学, 英语)
# A tibble: 4 × 5
学号 姓名 语文 数学 英语
<chr> <chr> <dbl> <dbl> <dbl>
1 01 赵雷 80 90 99
2 03 孙风 80 80 80
3 05 周梅 76 87 NA
4 07 郑竹 NA 89 98
36 查询不及格的课程
37 查询课程01的成绩大于等于80的学生学号和姓名
38 查询选修”张三”老师所授课程的学生中,成绩最高的学生信息及其成绩
# 方法1
score %>%
left_join(course, by = "课程编号") %>%
left_join(teacher, by = "教师编号") %>%
filter(教师姓名 == "张三") %>%
left_join(student, by = "学号") %>%
slice_max(成绩)
# A tibble: 1 × 9
学号 课程编号 成绩 课程名称 教师编号 教师姓名 姓名 生日 性别
<chr> <chr> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 01 02 90 数学 01 张三 赵雷 1990-01-01 男
# 方法2
teacher %>%
left_join(course, by = "教师编号") %>%
filter(教师姓名 == "张三") %>%
semi_join(score, ., by = "课程编号") %>%
slice_max(成绩, n = 1) %>%
left_join(student, by = "学号")
# A tibble: 1 × 6
学号 课程编号 成绩 姓名 生日 性别
<chr> <chr> <dbl> <chr> <chr> <chr>
1 01 02 90 赵雷 1990-01-01 男
39 查询不同课程成绩相同的学生学号、课程编号、学生成绩
40 查询每门课程成绩最好的前两名
41 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
42 检索至少选修两门课程的学生学号
43 查询选修了全部课程的学生信息
course %>%
left_join(score, by = "课程编号") %>%
select(-c(课程编号, 教师编号)) %>%
pivot_wider(names_from = 课程名称, values_from = 成绩) %>%
right_join(student, by = "学号") %>%
filter(if_all(2:4, \(x) !is.na(x))) %>%
select(-c(2:4))
# A tibble: 4 × 4
学号 姓名 生日 性别
<chr> <chr> <chr> <chr>
1 01 赵雷 1990-01-01 男
2 02 钱电 1990-12-21 男
3 03 孙风 1990-05-20 男
4 04 李云 1990-08-06 男
44 查询各学生的年龄: 按照出生日期来算,当前年月日<出生年月的月日,则年龄减1
# A tibble: 8 × 5
学号 姓名 生日 性别 年龄
<chr> <chr> <date> <chr> <dbl>
1 01 赵雷 1990-01-01 男 34
2 02 钱电 1990-12-21 男 33
3 03 孙风 1990-05-20 男 34
4 04 李云 1990-08-06 男 34
5 05 周梅 1991-12-01 女 32
6 06 吴兰 1992-03-01 女 32
7 07 郑竹 1989-07-01 女 35
8 08 王菊 1990-01-20 女 34
45 查询本周过生日的学生
- 修改列:将生日转化为日期型
- 根据条件筛选:生日周等于每周,筛选行