R Select()、Filter()、Arrange()、Pipeline 及示例

⚡ 智能摘要

R 语言中的 select、filter 和 Arrange 是 dplyr 包中的三个动词,它们可以将数据框简化为所需的列、行和顺序。本教程将演示如何将它们与管道运算符结合使用,处理一个包含 205 行的旅行时间数据集。

  • 📋 列选择: select(df, A, B) 保留命名列,select(df, A:C) 保留范围,select(df, -C) 删除一个列。
  • 🔎 行筛选: filter(df, condition) 保留匹配的行,条件用 & 符号表示 AND,用竖线表示 OR 组合。
  • 🔣 排序: arrange() 默认按升序排列行,desc() 反转任意单列。
  • 🔗 U型槽 OperaTOR: %>% 运算符将每个结果直接传递给下一个动词,因此不会有中间对象使环境变得混乱。
  • 🧹 辅助函数: starts_with()、contains() 和 where() 分别按模式或类型而不是名称选择列。
  • 📐 动词顺序很重要: 先进行初步筛选以缩小数据范围,然后再进行选择和整理,这样可以降低后续每一步的成本。

R 选择筛选排列管道

R 语言中的 dplyr 是什么?

dplyr 是 tidyverse 的数据操作包。它取代了基础包中的方括号表示法。 R 使用一组简短的动词,每个动词都以其执行的动作命名,并且每个动词都以数据框作为其第一个参数。这种一致的结构使得动词可以串联起来。

动词 法案 它做什么
选择() 保留或删除变量
过滤() 保留符合条件的行
安排() 按一列或多列重新排列行
变异() 创建或修改变量
总结() 整桌 将多行数据合并为单个统计信息
group_by() 整桌 将数据拆分,以便后续动词按组运行。

本教程涵盖前三个动词以及竖笛。 聚合函数教程 深入介绍 group_by() 和 summarise() 函数。

本教程中使用的数据集

dplyr 库包含用于在数据集中导航的实用动词。在本教程中,您将使用“出行时间”数据集。该数据集记录了驾驶员往返于家和工作地点之间的行程。数据集中包含十四个变量,其中包括:

  • DayOfWeek:确定司机使用汽车的星期几
  • 距离:旅程总距离
  • MaxSpeed:行程的最大速度
  • 总时间:旅程的长度(分钟)

该数据集包含 205 个观测值,骑行活动发生在 Monday 到星期五。

首先,您需要:

  • 加载数据集
  • 检查数据的结构。

dplyr 中一个很实用的函数是 glimpse()。它的作用与 R 基础函数 str() 相同,但它会为每个变量打印一行,包含变量类型和前几个值,这样在处理大型数据集时更容易浏览。

library(dplyr) 
PATH <- "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/travel_times.csv"
df <- read.csv(PATH)
glimpse(df)

输出:

## Observations: 205
## Variables: 14
## $ X              <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...
## $ Date           <fctr> 1/6/2012, 1/6/2012, 1/4/2012, 1/4/2012, 1/3/20...
## $ StartTime      <fctr> 16:37, 08:20, 16:17, 07:53, 18:57, 07:57, 17:3...
## $ DayOfWeek      <fctr> Friday, Friday, Wednesday, Wednesday, Tuesday,...
## $ GoingTo        <fctr> Home, GSK, Home, GSK, Home, GSK, Home, GSK, GS...
## $ Distance       <dbl> 51.29, 51.63, 51.27, 49.17, 51.15, 51.80, 51.37...
## $ MaxSpeed       <dbl> 127.4, 130.3, 127.4, 132.3, 136.2, 135.8, 123.2...
## $ AvgSpeed       <dbl> 78.3, 81.8, 82.0, 74.2, 83.4, 84.5, 82.9, 77.5,...
## $ AvgMovingSpeed <dbl> 84.8, 88.9, 85.8, 82.9, 88.1, 88.8, 87.3, 85.9,...
## $ FuelEconomy    <fctr> , , , , , , -, -, 8.89, 8.89, 8.89, 8.89, 8.89...
## $ TotalTime      <dbl> 39.3, 37.9, 37.5, 39.8, 36.8, 36.8, 37.2, 37.9,...
## $ MovingTime     <dbl> 36.3, 34.9, 35.9, 35.6, 34.8, 35.0, 35.3, 34.3,...
## $ Take407All     <fctr> No, No, No, No, No, No, No, No, No, No, No, No...
## $ Comments       <fctr> , , , , , , , , , , , , , , , Put snow tires o...	

显然需要仔细检查“评论”变量:第一个观测值全部为空。

sum(df$Comments =="")

Code 说明

  • sum(df$Comments == ""): 统计数据框 df 中 Comments 列值为空字符串的观测值数量

输出:

## [1] 181

数据加载完毕后,首先执行修剪列的操作。

选择()

我们将从 select() 动词开始。我们不一定需要所有变量,一个好的做法是只选择您认为相关的变量。

我们有 181 个缺失的观测值,几乎占数据集的 90%。如果您决定排除它们,您将无法继续分析。

另一种可能性是使用 select() 动词删除变量 Comment。

我们可以使用 select() 以不同的方式选择变量。请注意,第一个参数是数据集。

- `select(df, A, B ,C)`: Select the variables A, B and C from df dataset.
- `select(df, A:C)`: Select all variables from A to C from df dataset.
- `select(df, -C)`: Exclude C from the dataset from df dataset.	

您可以使用第三种方法来排除 Comments 变量。

step_1_df <- select(df, -Comments)
dim(df)

输出:

## [1] 205  14
dim(step_1_df)

输出:

## [1] 205  13

原始数据集有 14 个特征,而 step_1_df 有 13 个。

R语言中的select()辅助函数

当数据集包含数十个变量时,为每一列命名就变得不切实际。dplyr 提供了一些辅助函数,可以按模式或类型选择列。

帮手 选择列 例如:
starts_with() 以字符串开头 select(df, starts_with(“Avg”))
ends_with() 以字符串结尾 select(df, ends_with(“Time”))
包含() 在任意位置包含字符串 选择(df,包含(“速度”))
火柴() 匹配正则表达式 select(df, matches(“^Max|^Avg”))
在哪里() 满足类型测试要求 select(df, where(is.numeric))
一切() 尚未命名 select(df, TotalTime, everything())
# Keep only the timing columns
df %>% select(ends_with("Time"))

# Keep every numeric column
df %>% select(where(is.numeric))

# Move TotalTime to the front, keep the rest in place
df %>% select(TotalTime, everything())

还有两个动词可以与 select() 函数自然搭配使用。使用 rename(new_name = old_name) 可以在不删除列的情况下重命名列。ping 其他列,以及 relocate() 来移动列,而无需列出所有列。

过滤()

`filter()` 函数会保留满足特定条件的观测值。`filter()` 的工作方式与 `select()` 完全相同,您需要先传入数据框,然后再传入一个用逗号分隔的条件:

filter(df, condition)
arguments:
- df: dataset used to filter the data
- condition:  Condition used to filter the data	

一个标准

首先,您可以计算因子变量每个级别内的观测值数量。

table(step_1_df$GoingTo)

Code 说明

  • table():统计每个级别的观测值数量。它接受一个因子或字符变量。
  • 表(step_1_df$GoingTo): 统计前往每个目的地的行程次数

输出:

## 
##  GSK Home 
##  105  100	

函数 table() 指示有 105 次行程去往 GSK,还有 100 次行程去往家。

我们可以过滤数据以返回一个包含 105 个观测值的数据集和另一个包含 100 个观测值的数据集。

# Select observations where GoingTo == Home
select_home <- filter(df, GoingTo == "Home")
dim(select_home)

输出:

## [1] 100  14
# Select observations where GoingTo == GSK (work)
select_work <- filter(df, GoingTo == "GSK")
dim(select_work)

输出:

## [1] 105  14

多项标准

我们可以使用多个条件来筛选数据集。例如,您可以……trac观察结果显示,目的地为家,出行日期为星期三。

select_home_wed <- filter(df, GoingTo == "Home" & DayOfWeek == "Wednesday")
dim(select_home_wed)

输出:

## [1] 23 14

23 个观察结果符合该标准。

常用筛选条件和 OperaR 中的

filter() 函数会保留所有条件为 TRUE 的行。条件为 NA 的行会被删除,这种行为常常让初学者感到意外。

Opera器 例如:
== 等于 filter(df, GoingTo == “Home”)
!= 不等于 filter(df, DayOfWeek != “Monday“)
& 而且,两者都必须满足 filter(df, Distance > 50 & MaxSpeed > 130)
| 或者,两者都可能成立。 filter(df, DayOfWeek == “Monday” | DayOfWeek == “星期五”)
%在% 匹配向量中的任何值 filter(df, DayOfWeek %in% c(“Monday“, “星期五”))
之间() 落在某个数值范围内 filter(df, between(Distance, 48, 52))
是.na() 缺失值 filter(df, is.na(FuelEconomy))

养成三个习惯可以避免大部分 filter() 函数的错误。

  • 使用 %in% 代替链式 OR。 filter(df, DayOfWeek %in% c(“Monday”, “星期五”)) 比两个用竖线连接的 == 比较更短,也更不容易打错。
  • 永远不要用 == 来判断缺失值。 表达式 x == NA 返回的是 NA 而不是 TRUE,因此该行会被静默删除。请改用 is.na(x)。
  • 逗号表示“和”。 filter(df, a, b) 与 filter(df, a & b) 完全相同,这就是为什么本教程前面的示例两种方式都能正常工作的原因。

管道 Operator 在 dplyr

数据集的创建需要很多操作,例如:

  • 输入
  • 合并
  • 选择
  • 过滤
  • 等等

dplyr 库带有一个实用运算符 %>%,称为 它使数据处理更干净、更快捷、更不容易出错。

此运算符是一种执行步骤而不将中间步骤保存到硬盘的代码。如果您回到上面的示例,您可以选择感兴趣的变量并对其进行过滤。我们有三个步骤:

  • 步骤 1:导入数据:导入 GPS 数据
  • 步骤 2:选择数据:选择 GoingTo 和 DayOfWeek
  • 步骤 3:筛选数据:仅返回主页和星期三

我们可以用困难的方法来做这件事:

# Step 1
step_1 <- read.csv(PATH)

# Step 2 
step_2 <- select(step_1, GoingTo, DayOfWeek)

# Step 3 
step_3 <- filter(step_2, GoingTo == "Home", DayOfWeek == "Wednesday")

head(step_3)

输出:

##   GoingTo DayOfWeek
## 1    Home Wednesday
## 2    Home Wednesday
## 3    Home Wednesday
## 4    Home Wednesday
## 5    Home Wednesday
## 6    Home Wednesday	

这不是串联多个操作的便捷方式。每个中间结果都会保留在环境中,名称很快就会失去意义。

请改用管道运算符 %>%。只需在开始时命名一次数据框,后续所有步骤都将以此为基础。

管道基本语法

New_df <- df %>%
step 1 %>%
step 2 %>%
...
arguments
- New_df: Name of the new data frame 
- df: Data frame used to compute the step
- step: Instruction for each step
- Note: the last instruction does not need a trailing `%>%`, because nothing follows it
- Note: assigning the result to a new object is optional. Without it, the output prints in the console.

您可以按照上面列举的步骤创建您的第一个管道。

# Create the data frame filter_home_wed.It will be the object return at the end of the pipeline
filter_home_wed <- 

#Step 1
read.csv(PATH) %>% 

#Step 2
select(GoingTo, DayOfWeek) %>% 

#Step 3
filter(GoingTo == "Home",DayOfWeek == "Wednesday")
identical(step_3, filter_home_wed)

输出:

## [1] TRUE

这两个对象是相同的,因此管道操作用一条可读的语句产生了完全相同的结果。

安排()

先前的教程中,您将学习如何使用函数 sort() 对值进行排序。库 dplyr 具有其排序函数。它与管道配合得天衣无缝。arrange() 动词可以对一行或多行重新排序,可以按升序(默认)或降序排列。

- `arrange(A)`: Ascending sort of variable A
- `arrange(A, B)`: Ascending sort of variable A and B
- `arrange(desc(A), B)`: Descending sort of variable A and ascending sort of B

我们可以按照目的地对距离进行排序。

# Sort by destination and distance
step_2_df <- step_1_df %>%
    arrange(GoingTo, Distance)
head(step_2_df)

输出:

##     X       Date StartTime DayOfWeek GoingTo Distance MaxSpeed AvgSpeed
## 1 193  7/25/2011     08:06    Monday     GSK    48.32    121.2     63.4
## 2 196  7/21/2011     07:59  Thursday     GSK    48.35    129.3     81.5
## 3 198  7/20/2011     08:24 Wednesday     GSK    48.50    125.8     75.7
## 4 189  7/27/2011     08:15 Wednesday     GSK    48.82    124.5     70.4
## 5  95 10/11/2011     08:25   Tuesday     GSK    48.94    130.8     85.7
## 6 171  8/10/2011     08:13 Wednesday     GSK    48.98    124.8     72.8
##   AvgMovingSpeed FuelEconomy TotalTime MovingTime Take407All
## 1           78.4        8.45      45.7       37.0         No
## 2           89.0        8.28      35.6       32.6        Yes
## 3           87.3        7.89      38.5       33.3        Yes
## 4           77.8        8.45      41.6       37.6         No
## 5           93.2        7.81      34.3       31.5        Yes
## 6           78.8        8.54      40.4       37.3         No

R 语言中的 dplyr 动词:快速参考

下表列出了本教程中使用的每个动词,包括语法和每次调用的返回值:

动词 目的 Code 说明
一瞥 检查 df 的结构
glimpse(df)
与 str() 函数用途相同,更易于阅读。
选择() 选择/排除变量
select(df, A, B ,C)
选择变量 A、B 和 C
select(df, A:C)
选择从 A 到 C 的所有变量
select(df, -C)
排除 C
过滤() 保持行符合一个或多个条件
filter(df, condition1)
一个条件
filter(df, condition1 & condition2)
两个条件与 AND 结合
安排() 使用一个或多个变量对数据集进行排序
arrange(A)
变量 A 升序排序
arrange(A, B)
对变量 A 和 B 进行升序排序
arrange(desc(A), B)
对变量 A 进行降序排序,对变量 B 进行升序排序
%>% 在每个步骤之间创建管道
step 1 %>% step 2 %>% step 3

常见问题

magrittr %>% 管道随 dplyr 包一起提供,支持使用点号的占位符语法。原生 |> 管道在 R 4.1 版本中引入,无需任何包。两者都将左侧的结果传递给右侧的第一个参数。

不。每个 dplyr 函数都会返回一个新的数据帧,而不会修改输入数据。你必须将结果赋值给一个对象,或者通过管道将其传递给下一个对象,才能使更改生效。

与 NA 进行比较会返回 NA 而不是 TRUE,而 filter() 函数只保留 TRUE 的行。可以使用 is.na() 函数特意选择缺失值,或者使用 tidyr 包中的 drop_na() 函数删除缺失值。

AI模型的特征工程主要包括过滤行、选择列和排序。dplyr将这些步骤表示为易于审阅的流水线,方便审核人员进行检查,这对于训练数据集必须可复现的情况至关重要。

是的。AI 助手可以将括号子集操作转换为 select() 和 filter() 函数调用,并解释管道符。务必同时运行这两个版本并比较维度,因为 R 基础包和 dplyr 包处理缺失值的方式不同。

总结一下这篇文章: