第8讲:dplyr筛选与排序

数据分析与R语言

2026年09月22日

本讲导览

Data Wrangling with dplyr

本讲路线

  • 一、复习导入 ——base R筛选数据框够直观吗?
  • 二、管道符 ——把多个步骤串起来
  • 三、arrange() ——排序
  • 四、filter() ——筛选行
  • 五、select() ——选择列
  • 六、综合实战 ——串成一条流水线
  • 七、课堂总结与Exit Ticket ——“动词化”的数据处理思维

今天是项目二“数据准备”第二课,数据沿用第 7 课那套(一键复现)。

课前小测

复习一下第6、7课的内容,热热身

小测(2选择 + 2填空)

  1. 单选:对数据框按某一列排序,第6课学过的函数是? A. sort() B. order() C. arrange() D. filter()

  2. 单选:用 RStudio Project(.Rproj)打开一个项目后,默认的工作目录是? A. 上次退出R时的目录 B. 项目文件所在的文件夹 C. C盘根目录 D. 桌面

  3. 填空:readr包读取CSV文件最常用的函数是 ____()

  4. 填空:要加载readr包,应写作 ____

参考答案

一、复习导入与新课导论

base R筛选数据框够直观吗?

1.1 复习提问

第7课学的四个类型转换函数还记得几个?(as.numeric() / as.character() / as.factor() / as.Date())

1.2 情境导入

回顾第2课的向量筛选:revenue[revenue > 130]——这是对一列数字做筛选。

但如果是一个完整的数据框(company_data,含公司名、营收、评级多列),想“筛选出营收超过1000亿元的公司,只看公司名和评级两列,并按营收从高到低排序”——第6课的df[df$revenue > 500, ]能做,但写起来比较绕。

dplyr 是 tidyverse 的核心包,提供一套“动词”函数:arrange()排序、filter()筛选行、select()选列、mutate()新增列、summarise()汇总(后两个下节课学)——:把 base R 的“手动挡”升级成 dplyr 的“自动挡”。

1.3 先把本讲要用的数据准备好

本讲全程用这份虚构财务数据(锦城科技系列)——先跑一遍。

▶️ 查看代码
library(dplyr)              # 本讲要用(含管道符 %>%)

company_data <- data.frame(
  company = c("锦城科技", "蜀汉制造", "天府物流", "青羊金融", "锦江生物", "浣花实业"),
  revenue = c(1200.5, 980, 1560.3, 760.2, 2100, 890.75),
  cost    = c(800, 650, 1020, 500, 1400, 600),
  rating  = c("A", "B", "A", "C", "A", "B"))
company_data
   company revenue cost rating
1 锦城科技    1200  800      A
2 蜀汉制造     980  650      B
3 天府物流    1560 1020      A
4 青羊金融     760  500      C
5 锦江生物    2100 1400      A
6 浣花实业     891  600      B

二、管道符——把多个步骤串起来

管道符是 dplyr 工作流的“粘合剂”

2.1 管道符:把左边的结果交给右边

company_data原始数据(6 家公司)%>%select(company, revenue)① 选列%>%filter(revenue > 1000)② 筛选每一步的输出,就是下一步的输入 —— 所以代码可以「从上往下读」。

提示

x %>% f() 等价于 f(x);x %>% f(y) 等价于 f(x, y)——管道符把左边的结果,作为右边函数的第一个参数传进去。

2.2 一个最小例子

▶️ 查看代码
sqrt(16)        # 普通写法:先算16的平方根
[1] 4
▶️ 查看代码
16 %>% 
  sqrt()   # 管道写法:把16“传给”sqrt()
[1] 4
  • 本课程统一用 %>%(magrittr 提供、dplyr 自动加载)。R 4.1+ 另有一个原生管道 |>,但部分学校机房的 R 版本较低、不支持 |>,所以我们一律用 %>%

2.3 为什么要用管道——从“从内往外读”到“从上往下读”

▶️ 查看代码
filter(select(company_data, company, revenue), revenue > 1000)   # 不用管道
   company revenue
1 锦城科技    1200
2 天府物流    1560
3 锦江生物    2100
▶️ 查看代码
company_data %>%   # 用管道
  select(company, revenue) %>%
  filter(revenue > 1000)
   company revenue
1 锦城科技    1200
2 天府物流    1560
3 锦江生物    2100

2.4 课堂练习

把 round(sqrt(15)) 改写成管道形式(提示:从最里层的 sqrt(15) 开始往外“传”)

三、arrange()——排序

arrange() 让数据框按某一列或几列的值重新排队

3.1 arrange() 是怎么排的

同一份数据,行按「营收」重新排队——行数一行不变公司营收锦城科技1200.5蜀汉制造980.0天府物流1560.3青羊金融760.2锦江生物2100.0浣花实业890.75公司营收锦江生物2100.0天府物流1560.3锦城科技1200.5蜀汉制造980.0浣花实业890.75青羊金融760.2arrange()desc(revenue)行数一行不变只是换了个顺序默认是升序要降序,列名前加 desc()

3.2 升序:不写 desc() 就是从低到高

▶️ 查看代码
company_data %>% 
  arrange(revenue)          # 默认升序:营收从低到高
   company revenue cost rating
1 青羊金融     760  500      C
2 浣花实业     891  600      B
3 蜀汉制造     980  650      B
4 锦城科技    1200  800      A
5 天府物流    1560 1020      A
6 锦江生物    2100 1400      A

不写任何修饰就是从低到高——第一行是营收最低的青羊金融(760.2)。

3.3 降序:一定要记得加 desc()

▶️ 查看代码
company_data %>% 
  arrange(desc(revenue))    # 降序:营收从高到低
   company revenue cost rating
1 锦江生物    2100 1400      A
2 天府物流    1560 1020      A
3 锦城科技    1200  800      A
4 蜀汉制造     980  650      B
5 浣花实业     891  600      B
6 青羊金融     760  500      C

arrange() 默认是升序——很多同学第一反应以为是降序;想从高到低,一定要加 desc()。

3.4 多变量排序

▶️ 查看代码
company_data %>% 
  arrange(rating, desc(revenue))  # 多列:先按评级排,同评级内按营收降序
   company revenue cost rating
1 锦江生物    2100 1400      A
2 天府物流    1560 1020      A
3 锦城科技    1200  800      A
4 蜀汉制造     980  650      B
5 浣花实业     891  600      B
6 青羊金融     760  500      C

多列排序时,条件从左到右依次作为主关键字、次关键字——先按评级分组,同一评级内再按营收从高到低排。

3.5 课堂练习:用真实数据集练习排序

  1. 用 arrange() 对 R 内置数据集 mtcars 按 mpg(每加仑英里数)从高到低排序。
  2. 用 arrange() 对 R 内置数据集 iris 先按 Species 排序,同一物种内再按 Sepal.Length 从高到低排序。

四、filter()——筛选行

filter() 是 dplyr 里使用频率最高的函数

4.1 filter() 是怎么筛的

filter() 做的事:留下满足条件的行,其余整行剔除公司营收锦城科技1200.5蜀汉制造980.0天府物流1560.3青羊金融760.2锦江生物2100.0浣花实业890.75filter(revenue > 1000)6 行 → 3 行整行消失,但列一列不少留下的:锦城科技、天府物流、锦江生物

4.2 单条件筛选

▶️ 查看代码
company_data %>% 
  filter(revenue > 1000)   # 筛选营收超过1000(亿元)的公司
   company revenue cost rating
1 锦城科技    1200  800      A
2 天府物流    1560 1020      A
3 锦江生物    2100 1400      A

筛选逻辑和前面学的向量筛选一样,只是把对象从“一列数字”换成了“整个数据框”,条件写在逗号后面的参数里

4.3 &(且)与 |(或):两种完全不同的逻辑

表一表二&(且)两个条件都满足 → 剩 3 家表一表二|(或)满足一个即可 → 剩 5 家%in% 就是「或」的简写rating %in% c("A", "B")= rating == "A" | rating == "B"取值一多,%in% 比一连串 | 清爽得多

4.4 代码演示:同一个筛选,两种逻辑的差别

▶️ 查看代码
company_data %>% filter(revenue > 1000 & rating == "A")   # 且:都满足 → 3 家
   company revenue cost rating
1 锦城科技    1200  800      A
2 天府物流    1560 1020      A
3 锦江生物    2100 1400      A
▶️ 查看代码
company_data %>% filter(revenue > 1000 | rating == "B")   # 或:满足一个 → 5 家
   company revenue cost rating
1 锦城科技    1200  800      A
2 蜀汉制造     980  650      B
3 天府物流    1560 1020      A
4 锦江生物    2100 1400      A
5 浣花实业     891  600      B

4.5 %in%——更简洁的多值匹配

▶️ 查看代码
# 等价的啰嗦写法:filter(rating == "A" | rating == "B")
company_data %>% 
  filter(rating %in% c("A", "B"))   # %in% 表示“属于”,一多就清爽
   company revenue cost rating
1 锦城科技    1200  800      A
2 蜀汉制造     980  650      B
3 天府物流    1560 1020      A
4 锦江生物    2100 1400      A
5 浣花实业     891  600      B

4.6 课堂练习:用真实数据集练习筛选

用 R 内置数据集 airquality(1973年纽约每日空气质量观测)完成:

  1. 筛选出 Temp(华氏温度)大于90的记录(单条件)
  2. 筛选出 Month 等于7 且 Temp 大于85的记录(双条件“且”)
  3. 筛选出 Month 等于6 或 Month 等于9的记录(双条件“或”)

五、select()——选择列

选列,为数据“瘦身”

5.1 select() 是怎么挑列的

select() 做的事:挑出某些列,或者去掉某些列——行一行不动companyrevenuecostratingselect(company, revenue)只留这两列companyrevenuecostratingselect(-rating)去掉这一列,其余全留深蓝=保留 浅灰=丢弃

5.2 选列:只留下想要的

▶️ 查看代码
company_data %>% 
  select(company, revenue)     # 只保留公司名和营收两列
   company revenue
1 锦城科技    1200
2 蜀汉制造     980
3 天府物流    1560
4 青羊金融     760
5 锦江生物    2100
6 浣花实业     891

财务场景:原始数据常有几十列,某次分析只需要其中几列——select() 能快速给数据“瘦身”。

5.3 排除列:用减号去掉不要的

▶️ 查看代码
company_data %>% 
  select(-rating)              # 排除 rating,其余列全部保留
   company revenue cost
1 锦城科技    1200  800
2 蜀汉制造     980  650
3 天府物流    1560 1020
4 青羊金融     760  500
5 锦江生物    2100 1400
6 浣花实业     891  600

列多的时候,用 - 比把要保留的列名一个个列出来省事,也不怕漏列。

5.4 课堂练习:用真实数据集练习选列

用 R 内置数据集 mtcars 完成:

  1. 选取 mpg、cyl、hp 三列(正向选择)
  2. 排除 vs 和 am 两列,保留其余所有列(排除选择)
  3. 选取并把列顺序调整为 gear、mpg、hp,其余列放最后(用 everything())

5.5 课堂练习:三个动词综合运用

用一条管道完成:筛选出评级为A的公司 → 按营收从高到低排序 → 只保留公司名和营收两列

六、综合实战——串成一条流水线

把今天学的动词串成一条连贯的流水线

6.1 实战任务

模拟一份真实的财务分析任务:从 company_data 出发,完成——

  1. 只保留公司名、营收、评级三列
  2. 筛选出营收超过500亿元且评级为A的公司
  3. 按营收从高到低排序
  4. 用 write_csv() 导出结果(回顾第7课的导出)

提示

建议先用管道写一个“一气呵成”的版本,再用 base R 写一遍同样逻辑,对比两者的可读性。

6.2 参考实现

每一步一个“动词”,代码本身就是操作说明书——这正是“代码即流程”的体现

6.3 课堂展示

现场邀请1-2名学生展示自己的管道写法与 base R 写法的对比

七、课堂总结与Exit Ticket

“动词化”的数据处理思维

7.1 本讲知识回顾

flowchart LR
    A["管道符<br/>把步骤串起来"] --> B["arrange()<br/>排序"]
    B --> C["filter()<br/>筛选行"]
    C --> D["select()<br/>选列瘦身"]
    D --> E["综合实战<br/>一条流水线"]

    style A fill:#1a3a5c,color:#fff
    style B fill:#2e5984,color:#fff
    style C fill:#7a4419,color:#fff
    style D fill:#375623,color:#fff
    style E fill:#6b3d8f,color:#fff

管道符(%>%)把数据传下去,arrange() 排序、filter() 筛选行、select() 选列——这就是 dplyr“动词化”工作的核心范式:数据从左流到右,每一步做什么清清楚楚

7.2 学习成果自查

对照一下,今天这几件事你都做到了吗?

  • ✓ 能用管道符 %>% 把多个处理步骤串起来
  • ✓ 能用 arrange() 排序(记得 desc() 降序)
  • ✓ 能用 filter() 做单条件与多条件(&、|、%in%)筛选
  • ✓ 能用 select() 选择、排除列或调整列顺序
  • ✓ 能对比 dplyr 与 base R 写法的差异,体会“代码即流程”

提示

如果有没打勾的,下课后一定要找同学或老师补上,不要留到下一讲。

7.3 Exit Ticket —— 写给自己的三个问题

请花1分钟,在纸条或在线问卷上简要回答:

  1. 管道符 %>% 改变了代码的“阅读方向”,具体是怎么变的?
  2. arrange() 默认是升序还是降序?想要降序要加什么?
  3. filter() 里 & 和 | 有什么区别?什么时候用 %in% 更合适?

课后作业

dplyr排序、筛选、选列综合练习

本次作业以《实验报告3》的形式布置,共8道题,全部基于R自带的 mtcars 数据集,无需读取任何外部文件:

  • 排序(2题):分别按单一变量、按两个变量(一升一降)排序
  • 行筛选(3题):单条件、双条件“且”、双条件“或”
  • 列选择(3题):正向选择、排除选择、选择并调整列顺序(第8题综合运用 select()、filter()、arrange() 三个动词)

提交要求

按《实验报告3》模板要求,在“实现代码”处和“效果截图”处粘贴运行结果截图,完成后提交该Word文档。

下讲预告

第9讲:数据变换与汇总——mutate()新增/修改列、group_by()分组、summarise()汇总统计

下讲内容

  • mutate():新增或修改列
  • group_by() + summarise():分组汇总统计
  • 把今天学的筛选排序,变成更完整的数据处理流水线

提示

课前准备:保留好今天写的筛选排序代码,下节课会在这个基础上继续添加新的处理步骤。

谢谢!

第8讲:dplyr筛选与排序

"Good data analysis is about clear communication." 数据处理的每一步都应当清晰可读、有据可查——就像审计工作底稿逐步留痕。

朱 奇 | 锦城大学 · 财会学院