《R for Data Science (2e)》免费中文翻译 (第3章) --- Data transformation(1)
写在前面
本系列推文为《R for Data Science (2)》的中文翻译版本。所有内容都通过开源免费的方式上传至Github,欢迎大家参与贡献,详细信息见:
Books-zh-cn 项目介绍:
Books-zh-cn:开源免费的中文书籍社区
r4ds-zh-cn Github 地址:
https://github.com/Books-zh-cn/r4ds-zh-cn
r4ds-zh-cn 网站地址:
https://books-zh-cn.github.io/r4ds-zh-cn/
目录
-
3.1 介绍
-
3.2 行
-
3.3 列
3.1 介绍
可视化是生成洞察力的重要工具,但很少有数据以完全符合你所需的形式提供,以制作你想要的图形。通常情况下,你需要创建一些新的变量或摘要统计信息来回答你的问题,或者你可能只是想重命名变量或重新排序观测结果,以便更轻松地处理数据。在本章中,你将学习如何使用 dplyr 包进行数据转换(data transformation),并使用关于 2013 年从纽约市出发的航班的新数据集来介绍这些内容,并且你还将学习更多相关的知识!
本章的目标是为你提供转换数据框的所有关键工具的概述。我们将从对数据框的行和列进行操作的函数开始,然后再回到管道操作符的讨论,这是一个重要的工具,用于组合操作。然后,我们将介绍如何使用分组进行操作。最后,我们将通过一个案例研究展示这些函数的实际应用,并在后续章节中更详细地讨论这些函数,以便深入研究特定类型的数据 (e.g., numbers, strings, dates)。
3.1.1 先决条件
在本章中,我们将关注 dplyr 包,它是 tidyverse 的另一个核心成员。我们将使用 nycflights13 包中的数据说明关键思想,并使用 ggplot2 帮助我们理解数据。
library(nycflights13)
library(tidyverse)
#> ── Attaching core tidyverse packages ───────────────────── tidyverse 2.0.0 ──
#> ✔ dplyr 1.1.4 ✔ readr 2.1.5
#> ✔ forcats 1.0.0 ✔ stringr 1.5.1
#> ✔ ggplot2 3.5.2 ✔ tibble 3.3.0
#> ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
#> ✔ purrr 1.0.4
#> ── Conflicts ─────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag() masks stats::lag()
#> ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
请仔细注意加载 tidyverse 时打印的冲突消息(conflicts message)。它告诉你 dplyr 覆盖了 base R 中的一些函数。如果你想在加载 dplyr 后使用这些函数的 base 版本,你需要使用它们的全名:stats::filter()
和 stats::lag()
。到目前为止,我们大多忽略了一个函数来自哪个包,因为大多数时候它并不重要。但是,了解包可以帮助您找到帮助并找到相关函数,因此当我们需要准确了解某个函数来自哪个包时,我们将使用与 R 相同的语法:packagename::functionname()
。
3.1.2 nycflights13
为了探索基本的 dplyr 动词(verbs),我们将使用 nycflights13::flights
。该数据集包含 2013 年从纽约市起飞的所有 336,776 航班。数据来自美国 Bureau of Transportation Statistics,记录在 ?flights
中。
flights
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 336,770 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
flights
是一个 tibble,一种特殊类型的 data frame,tidyverse 使用它来避免一些常见的问题。tibbles 和 data frame 之间最重要的区别是 tibbles 的打印方式;它们是为大型数据集设计的,因此它们只显示前几行,并且只显示适合一个屏幕的列。有几个选项可以查看所有内容。如果您使用的是 RStudio,最方便的可能是 View(flights)
,它将打开一个交互式的可滚动和可过滤的视图。另外,您可以使用 print(flights, width = Inf)
来显示所有列,或使用 glimpse()
:
glimpse(flights)
#> Rows: 336,776
#> Columns: 19
#> $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013…
#> $ month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
#> $ day <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
#> $ dep_time <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 55…
#> $ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 60…
#> $ dep_delay <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2,…
#> $ arr_time <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 8…
#> $ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 8…
#> $ arr_delay <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7,…
#> $ carrier <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6"…
#> $ flight <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301…
#> $ tailnum <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N…
#> $ origin <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LG…
#> $ dest <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IA…
#> $ air_time <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149…
#> $ distance <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 73…
#> $ hour <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6…
#> $ minute <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59…
#> $ time_hour <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-0…
在这两个视图中,变量名称后跟缩写,告诉您每个变量的类型:<int>
是整数(integer)的缩写,<dbl>
是双精度(double)(又名实数)的缩写,<chr>
用于字符(character)(也称为字符串),<dttm>
用于日期时间(date-time)。这些很重要,因为您可以对列执行的操作在很大程度上取决于其”类型”。
3.1.3 dplyr 基础
您将学习主要的 dplyr verbs(functions),这将使您能够解决绝大多数数据操作挑战。但在我们讨论它们的个体差异之前,有必要先说明一下它们的共同点:
-
第一个参数始终是一个 data frame。
-
随后的参数通常使用变量名称(不带引号)描述要对哪些列进行操作。
-
输出总是一个新的 data frame。
因为每个 verb 都擅长做一件事,解决复杂问题通常需要组合多个 verbs,我们将使用竖线 |>
来实现。我们将在 Section 3.4
中更多地讨论管道,但简而言之,管道将其左侧的东西传递给右侧的函数,因此 x |> f(y)
等价于 f(x, y)
,而 x |> f(y) |> g(z)
等价于 g(f(x, y), z)
。管道的最简单发音是 “then”。即使您尚未了解详细信息,也可以了解以下代码:
flights |>filter(dest == "IAH") |> group_by(year, month, day) |> summarize(arr_delay = mean(arr_delay, na.rm = TRUE))
dplyr 的 verbs 根据操作对象分为四组:rows, columns, groups, or tables。在接下来的部分中,您将学习 rows、columns 和 groups 最重要的 verbs,然后我们将回到 Chapter 19
中用于 tables 的连接动词。让我们开始吧!
3.2 行
对数据集的行进行操作的最重要的 verbs 是 filter()
,它改变了哪些行存在而不改变它们的顺序,以及 arrange()
,它改变了行的顺序而不改变存在的行。这两个函数只影响行,列保持不变。我们还将讨论 distinct()
,它可以找到具有唯一值的行,但与 arrange()
和 filter()
不同的是,它还可以选择性地修改列。
3.2.1 filter()
filter()
允许您根据列的值保留行。第一个参数是 data frame。第二个和后续参数是必须为真才能保留该行的条件。例如,我们可以找到所有晚点超过 120 分钟(两小时)的航班:
flights |> filter(dep_delay > 120)
#> # A tibble: 9,723 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 848 1835 853 1001 1950
#> 2 2013 1 1 957 733 144 1056 853
#> 3 2013 1 1 1114 900 134 1447 1222
#> 4 2013 1 1 1540 1338 122 2020 1825
#> 5 2013 1 1 1815 1325 290 2120 1542
#> 6 2013 1 1 1842 1422 260 1958 1535
#> # ℹ 9,717 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
除了 >
(大于),您还可以使用 >=
(大于或等于)、<
(小于)、<=
(小于或等于)、==
(等于)和 !=
(不等于)。您还可以将条件与 &
或 ,
结合起来以指示 “and”(检查两个条件)或与 |
结合以指示 “or”(检查任一条件):
# Flights that departed on January 1
flights |> filter(month == 1 & day == 1)
#> # A tibble: 842 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 836 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …# Flights that departed in January or February
flights |> filter(month == 1 | month == 2)
#> # A tibble: 51,955 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 51,949 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
组合 |
和 ==
时有一个有用的快捷方式:%in%
。它保留变量等于右侧值之一的行:
# A shorter way to select flights that departed in January or February
flights |> filter(month %in% c(1, 2))
#> # A tibble: 51,955 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 51,949 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
我们将在 Chapter 12
中更详细地回到这些比较和逻辑运算符。
当你运行 filter()
时,dplyr 执行过滤操作,创建一个新的数据框,然后打印它。它不会修改现有的 flights
数据集,因为 dplyr 函数从不修改其输入。要保存结果,您需要使用赋值运算符,<-
:
jan1 <- flights |> filter(month == 1 & day == 1)
3.2.2 常见错误
当您开始使用 R 时,最容易犯的错误是在测试相等性时使用 =
而不是 ==
。filter()
会在发生这种情况时通知您:
flights |> filter(month = 1)
#> Error in `filter()`:
#> ! We detected a named input.
#> ℹ This usually means that you've used `=` instead of `==`.
#> ℹ Did you mean `month == 1`?
另一个错误是你像用英语那样写 “or” 语句:
flights |> filter(month == 1 | 2)
这个能够工作,因为它不会抛出错误,但它不会得到你想要的结果,因为 |
首先检查条件 month == 1
然后检查条件 2
,这不是一个明智的检查条件。我们将在 Section 12.3.2
中详细了解这里发生的事情以及原因。
3.2.3 arrange()
arrange()
根据列(columns)的值更改行(rows)的顺序。它接受一个 data frame 和一组要按顺序排列的列名(column names)(或更复杂的表达式)。如果提供多个列名(column names),每个额外的列将用于解决前面列的值相等的情况。例如,下面的代码按照出发时间排序,该时间跨越了四列。我们首先获取最早的年份(years),然后在一年内获取最早的月份(months),以此类推。
flights |> arrange(year, month, day, dep_time)
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 336,770 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
在 arrange()
内部,您可以对列使用 desc()
函数,以便按降序(从大到小)重新排序数据框。例如,以下代码按延误时间从最长到最短的顺序排序航班:
flights |> arrange(desc(dep_delay))
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> 4 2013 9 20 1139 1845 1014 1457 2210
#> 5 2013 7 22 845 1600 1005 1044 1815
#> 6 2013 4 10 1100 1900 960 1342 2211
#> # ℹ 336,770 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
请注意,行的数量没有改变 – 我们只是重新排列了数据,而没有对其进行筛选。
3.2.4 distinct()
distinct()
函数用于在数据集中查找所有唯一的行,因此从技术上讲,它主要操作行。然而,大多数情况下,您希望获取某些变量的唯一组合,因此您也可以选择性地提供列名:
# Remove duplicate rows, if any
flights |> distinct()
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 336,770 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …# Find all unique origin and destination pairs
flights |> distinct(origin, dest)
#> # A tibble: 224 × 2
#> origin dest
#> <chr> <chr>
#> 1 EWR IAH
#> 2 LGA IAH
#> 3 JFK MIA
#> 4 JFK BQN
#> 5 LGA ATL
#> 6 EWR ORD
#> # ℹ 218 more rows
另外,如果您在筛选唯一行时想要保留其他列,可以使用 .keep_all = TRUE
选项。
flights |> distinct(origin, dest, .keep_all = TRUE)
#> # A tibble: 224 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 218 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
并非巧合,所有这些唯一的航班都是在 1 月 1 日:distinct()
函数将找到数据集中唯一行的第一个出现,并丢弃其余的重复行。
如果您想找到每个唯一行的出现次数,最好将 distinct()
替换为 count()
函数,并使用 sort = TRUE
参数按出现次数的降序排列它们。您可以在 Section 13.3
中了解更多关于 count()
函数的内容。
flights |>count(origin, dest, sort = TRUE)
#> # A tibble: 224 × 3
#> origin dest n
#> <chr> <chr> <int>
#> 1 JFK LAX 11262
#> 2 LGA ATL 10263
#> 3 LGA ORD 8857
#> 4 JFK SFO 8204
#> 5 LGA CLT 6168
#> 6 EWR ORD 6100
#> # ℹ 218 more rows
3.2.5 练习
-
在每个条件的单个管道中,找到满足条件的所有航班(flights):
-
到达延迟了两个或更长时间
-
Flew 到 Houston (
IAH
orHOU
) -
由 United, American, 或 Delta 运营
-
在夏天离开 (July, August, and September)
-
迟到了超过两个小时,但没有晚出发
-
被延迟至少一个小时,但在飞行中弥补了30分钟以上
-
对
flights
进行排序以查找起飞延误(departure delays)时间最长的航班。查找早上最早起飞的航班。 -
对
flights
进行排序以找到最快的航班。(提示:尝试在你的函数中包含一个数学计算。) -
2013 年每天都有航班吗?
-
哪些航班飞行距离最远?哪个航班飞行距离最短?
-
如果同时使用
filter()
和arrange()
,那么使用它们的顺序有什么关系吗?为什么/为什么不?考虑结果以及功能必须完成的工作量。
3.3 列
有四个重要的 verbs 可以在不更改行的情况下影响列:mutate()
创建从现有列派生的新列,select()
更改存在的列,rename()
更改列的名称,relocate()
更改列的位置。
3.3.1 mutate()
mutate()
的工作是添加根据现有列计算的新列。在转换(transform)章节中,您将学习大量可用于操作不同类型变量的函数。现在,我们将坚持使用基本代数,它允许我们计算 gain
、延迟航班在空中补足的时间以及以英里/小时为单位的 speed
:
flights |> mutate(gain = dep_delay - arr_delay,speed = distance / air_time * 60)
#> # A tibble: 336,776 × 21
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 336,770 more rows
#> # ℹ 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
默认情况下,mutate()
会在数据集的右侧添加新列,这使得很难看出这里发生了什么。我们可以使用 .before
参数将变量添加到左侧:
flights |> mutate(gain = dep_delay - arr_delay,speed = distance / air_time * 60,.before = 1)
#> # A tibble: 336,776 × 21
#> gain speed year month day dep_time sched_dep_time dep_delay arr_time
#> <dbl> <dbl> <int> <int> <int> <int> <int> <dbl> <int>
#> 1 -9 370. 2013 1 1 517 515 2 830
#> 2 -16 374. 2013 1 1 533 529 4 850
#> 3 -31 408. 2013 1 1 542 540 2 923
#> 4 17 517. 2013 1 1 544 545 -1 1004
#> 5 19 394. 2013 1 1 554 600 -6 812
#> 6 -16 288. 2013 1 1 554 558 -4 740
#> # ℹ 336,770 more rows
#> # ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>, …
.
表示 .before
是函数的参数,而不是我们正在创建的第三个新变量的名称。您还可以使用 .after
来在变量之后添加,并且在 .before
和 .after
中都可以使用变量名而不是位置。例如,我们可以在 day
之后添加新变量:
flights |> mutate(gain = dep_delay - arr_delay,speed = distance / air_time * 60,.after = day)
或者,您可以使用 .keep
参数控制保留哪些变量。一个特别有用的参数是 "used"
,它指定我们只保留在 mutate()
步骤中涉及或创建的列。例如,以下输出将仅包含变量 dep_delay
, arr_delay
, air_time
, gain
, hours
, and gain_per_hour
。
flights |> mutate(gain = dep_delay - arr_delay,hours = air_time / 60,gain_per_hour = gain / hours,.keep = "used")
请注意,由于我们尚未将上述计算的结果分配回 flights
,因此新变量 gain
、hours
、gain_per_hour
只会被打印出来,而不会存储在数据框中。如果我们希望它们在数据框中可用以供将来使用,我们应该仔细考虑是否要将结果分配回 flights
,用更多变量覆盖原始数据框,或者分配给一个新对象。通常,正确的答案是一个新对象,该对象以信息性命名以指示其内容,例如 delay_gain
,但您也可能有充分的理由覆盖 flights
。
3.3.2 select()
获取包含数百甚至数千个变量的数据集并不少见。在这种情况下,第一个挑战通常只是关注您感兴趣的变量。select()
允许您使用基于变量名称的操作快速放大有用的子集:
-
按名称选择列:
flights |> select(year, month, day)
-
选择 year 和 day(含)之间的所有列:
flights |> select(year:day)
-
选择除了 year 到 day(含)以外的所有列:
flights |> select(!year:day)
您也可以使用 -
代替 !
(您很可能会在野外看到它);我们推荐 !
因为它读起来像 “not”,并且与 &
和 |
结合得很好。
-
选择所有 characters 列:
flights |> select(where(is.character))
您可以在 select()
中使用许多辅助函数:
-
starts_with("abc")
: 匹配以 “abc” 开头的名称。 -
ends_with("xyz")
: 匹配以 “xyz” 结尾的名称。 -
contains("ijk")
: 匹配包含 “ijk” 的名称。 -
num_range("x", 1:3)
: 匹配x1
、x2
和x3
。
有关详细信息,请参阅 ?select
。一但你了解正则表达式(the topic of Chapter 15
),您还可以使用 matches()
来选择与模式匹配的变量。
您可以在使用 =
在 select()
时重命名变量。新名称出现在 =
的左侧,旧变量出现在右侧:
flights |> select(tail_num = tailnum)
#> # A tibble: 336,776 × 1
#> tail_num
#> <chr>
#> 1 N14228
#> 2 N24211
#> 3 N619AA
#> 4 N804JB
#> 5 N668DN
#> 6 N39463
#> # ℹ 336,770 more rows
3.3.3 rename()
如果你想保留所有现有变量并且只想重命名一些变量,你可以使用 rename()
而不是 select()
:
flights |> rename(tail_num = tailnum)
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # ℹ 336,770 more rows
#> # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>, …
如果你有一堆命名不一致的列,并且手动修复它们会很痛苦,请查看 janitor::clean_names()
,它提供了一些有用的自动清理。
3.3.4 relocate()
使用 relocate()
移动变量。您可能希望将相关变量收集在一起或将重要变量移到前面。默认情况下,relocate()
将变量移动到前面:
flights |> relocate(time_hour, air_time)
#> # A tibble: 336,776 × 19
#> time_hour air_time year month day dep_time sched_dep_time
#> <dttm> <dbl> <int> <int> <int> <int> <int>
#> 1 2013-01-01 05:00:00 227 2013 1 1 517 515
#> 2 2013-01-01 05:00:00 227 2013 1 1 533 529
#> 3 2013-01-01 05:00:00 160 2013 1 1 542 540
#> 4 2013-01-01 05:00:00 183 2013 1 1 544 545
#> 5 2013-01-01 06:00:00 116 2013 1 1 554 600
#> 6 2013-01-01 05:00:00 150 2013 1 1 554 558
#> # ℹ 336,770 more rows
#> # ℹ 12 more variables: dep_delay <dbl>, arr_time <int>, …
您还可以使用 .before
和 .after
参数指定放置它们的位置,就像在 mutate()
中一样:
flights |> relocate(year:dep_time, .after = time_hour)
flights |> relocate(starts_with("arr"), .before = dep_time)
3.3.5 练习
-
比较
dep_time
,sched_dep_time
, 和dep_delay
。您认为这三个数字之间有何关联? -
尽可能多地集思广益,从
flights
中选择dep_time
、dep_delay
、arr_time
和arr_delay
。 -
如果您在
select()
调用中多次指定同一个变量的名称,会发生什么情况? -
any_of()
函数有什么作用?为什么将它与该载体结合使用会有所帮助?
variables <- c("year", "month", "day", "dep_delay", "arr_delay")
-
运行以下代码的结果是否让您感到惊讶?默认情况下,select helpers 如何处理大写和小写?你怎么能改变这个默认值?
flights |> select(contains("TIME"))
-
将
air_time
重命名为air_time_min
以指示测量单位并将其移至数据框的开头。 -
为什么以下不起作用,错误是什么意思?
flights |> select(tailnum) |> arrange(arr_delay)
#> Error in `arrange()`:
#> ℹ In argument: `..1 = arr_delay`.
#> Caused by error:
#> ! object 'arr_delay' not found
--------------- 未完待续 ---------------
本期翻译贡献:
-
@TigerZ生信宝库