R数据科学》学习笔记|Note4:使用dplyr进行数据转换(上)

原文链接:

R数据科学》学习笔记|Note4:使用dplyr进行数据转换(上)

3.1

简介

一般来说,你需要创建一些新变量或者摘要统计量,还可能对变量进行重命名或对观测值进行重新排序,以便数据更容易处理。你将在本章中学会如何进行这些甚至更多操作,本章将教会你如何使用 dplyr 包来转换数据,并介绍一个新的数据集:2013 年从纽约市出发的航班信息。

3.1.1

准备工作

本章将重点讨论如何使用 tidyverse 中的另一个核心 R 包—dplyr 包。我们使 用nycflights13 包中的数据来说明 dplyr 包的核心理念,并使用 ggplot2 来帮助我们理解数据。

1BiocManager::install('nycflights13')

2library(nycflights13)

3library(tidyverse)

3.1.2

nycflights13

为了介绍 dplyr 中的基本数据操作,我们需要使用 nycflights13::flights。这个数据框包含了 2013 年从纽约市出发的所有 336 776 次航班的信息。该数据来自于美国交通统计局,可以使用 ?flights 查看其说明文档:

1> flights

2# A tibble: 336,776 x 19

3    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

4                                           

5 1  2013     1     1      517            515         2      830            819        11

6 2  2013     1     1      533            529         4      850            830        20

7 3  2013     1     1      542            540         2      923            850        33

8 4  2013     1     1      544            545        -1     1004           1022       -18

9 5  2013     1     1      554            600        -6      812            837       -25

10 6  2013     1     1      554            558        -4      740            728        12

11 7  2013     1     1      555            600        -5      913            854        19

12 8  2013     1     1      557            600        -3      709            723       -14

13 9  2013     1     1      557            600        -3      838            846        -8

1410  2013     1     1      558            600        -2      753            745         8

15# ... with 336,766 more rows, and 10 more variables: carrier , flight ,

16#   tailnum , origin , dest , air_time , distance , hour ,

17#   minute , time_hour 

这个数据框的输出和我们以前用过的其他数据框有一点差别:只显示了前几行和适合屏幕宽度的几列。(要想看到整个数据集,可以使用 View(flights) 在 RStudio查看器中打开数据集。)

列名下面有一行 3 个或 4 个字母的缩写。它们描述了每个变量的类型。

• int 表示整数型变量。

• dbl 表示双精度浮点数型变量,或称实数。

• chr 表示字符向量,或称字符串。

• dttm 表示日期时间(日期 + 时间)型变量。

还有另外 3 种常用的变量类型,虽然没有在这个数据集中出现,但很快就会在本书后面遇到。 

• lgl 表示逻辑型变量,是一个仅包括 TRUE 和 FALSE 的向量。

• fctr 表示因子,R 用其来表示具有固定数目的值的分类变量。

• date 表示日期型变量。

3.1.3

dplyr 基础

本章将学习 5 个 dplyr 核心函数。

• 按值筛选观测(filter())。

• 对行进行重新排序(arrange() )。

• 按名称选取变量(select() )。

• 使用现有变量的函数创建新变量(mutate() )。

• 将多个值总结为一个摘要统计量(summarize())。

这些函数都可以和 group_by() 函数联合起来使用,group_by() 函数可以改变以上每个函数的作用范围,让其从在整个数据集上操作变为在每个分组上分别操作。这 6 个函数构成了数据处理语言的基本操作。

3.2

使用filter() 筛选行

filter() 函数可以基于观测的值筛选出一个观测子集。第一个参数是数据框名称,第二个参数以及随后的参数是用来筛选数据框的表达式。例如,我们可以使用以下代码筛选出 1月 1 日的所有航班:

1> filter(flights, month == 1, day == 1)

2# A tibble: 842 x 19

3    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

4                                           

5 1  2013     1     1      517            515         2      830            819        11

6 2  2013     1     1      533            529         4      850            830        20

7 3  2013     1     1      542            540         2      923            850        33

8 4  2013     1     1      544            545        -1     1004           1022       -18

9 5  2013     1     1      554            600        -6      812            837       -25

10 6  2013     1     1      554            558        -4      740            728        12

11 7  2013     1     1      555            600        -5      913            854        19

12 8  2013     1     1      557            600        -3      709            723       -14

13 9  2013     1     1      557            600        -3      838            846        -8

1410  2013     1     1      558            600        -2      753            745         8

15# ... with 832 more rows, and 10 more variables: carrier , flight , tailnum ,

16#   origin , dest , air_time , distance , hour , minute ,

17#   time_hour 

如果运行这行代码,dplyr 就会执行筛选操作,并返回一个新数据框。dplyr 函数从来不修改输入,因此,如果想要保存函数结果,那么你就需要使用赋值操作符 <-:

1jan1 <- filter(flights, month == 1, day == 1)

R 要么输出结果,要么将结果保存在一个变量中。如果想同时完成这两种操作,那么你可以用括号将赋值语句括起来:

1> (dec25 <- filter(flights, month == 12, day == 25))

2# A tibble: 719 x 19

3    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

4                                           

5 1  2013    12    25      456            500        -4      649            651        -2

6 2  2013    12    25      524            515         9      805            814        -9

7 3  2013    12    25      542            540         2      832            850       -18

8 4  2013    12    25      546            550        -4     1022           1027        -5

9 5  2013    12    25      556            600        -4      730            745       -15

10 6  2013    12    25      557            600        -3      743            752        -9

11 7  2013    12    25      557            600        -3      818            831       -13

12 8  2013    12    25      559            600        -1      855            856        -1

13 9  2013    12    25      559            600        -1      849            855        -6

1410  2013    12    25      600            600         0      850            846         4

15# ... with 709 more rows, and 10 more variables: carrier , flight , tailnum ,

16#   origin , dest , air_time , distance , hour , minute ,

17#   time_hour 

3.2.1

比较运算符

为了有效地进行筛选,你必须知道如何使用比较运算符来选择观测。R 提供了一套标准的比较运算符:>、>=、<、<=、!=(不等于)和 ==(等于)。当开始使用 R 时,最容易犯的错误就是使用 = 而不是 == 来测试是否相等。

在使用 == 进行比较时,你可能还会遇到另一个常见问题:浮点数。下面的结果可能会令你目瞪口呆:

1> sqrt(2) ^ 2 == 2

2[1] FALSE

3> #> [1] FALSE

4> 1/49 * 49 == 1

5[1] FALSE

计算机使用的是有限精度运算(显然无法存储无限位的数),因此请记住,你看到的每个数都是一个近似值。比较浮点数是否相等时,不能使用 ==,而应该使用 near()

1near(sqrt(2) ^ 2, 2)

2#> [1] TRUE

3near(1 / 49 * 49, 1)

4#> [1] TRUE

3.2.2

逻辑运算符

filter() 中的多个参数是由“与”组合起来的:每个表达式都必须为真才能让一行观测包含在输出中。如果要实现其他类型的组合,你需要使用布尔运算符:& 表示“与”、| 表示“或”、! 表示“非”。下图给出了布尔运算的完整集合。

以下代码可以找出 11 月或 12 月出发的所有航班:

1filter(flights, month == 11 | month == 12)

表达式中的运算顺序和语言中的是不一样的。你不能写成 filter(flights, month == 11 |12) 这种形式。这种形式的文字翻译确实是“找出 11 月或 12 月出发的所有航班”,但在代码中则不是这个意思,代码中的含义是找出所有出发月份为 11 | 12 的航班。11 | 12 这个逻辑表达式的值为 TRUE,在数字语境中(如本例),TRUE 就是 1,所以这段代码找出的不是 11 月或 12 月出发的航班,而是 1 月出发的所有航班。

这种问题有一个有用的简写形式:x %in% y。这会选取出 x 是 y 中的一个值时的所有行。我们可以使用这种形式重写上面的代码:

1nov_dec <- filter(flights, month %in% c(11, 12))

有时你可以使用德摩根定律将复杂的筛选条件进行简化:!(x & y)等价于

!x | !y!(x |y)等价于 !x & !y。例如,如果想要找出延误时间(到达或出发)不多于 2 小时的航班,那么使用以下两种筛选方式均可:

1filter(flights, !(arr_delay > 120 | dep_delay > 120))

2filter(flights, arr_delay <= 120, dep_delay <= 120)

3.2.3

缺失值

的一个重要特征使得比较运算更加复杂,这个特征就是缺失值,或称 NA(not available,不可用)。NA 表示未知的值,因此缺失值是“可传染的”。如果运算中包含了未知值,那么运算结果一般来说也是个未知值:

1NA > 5

2#> [1] NA

310 == NA

4#> [1] NA

5NA + 10

6#> [1] NA

7NA / 2

8#> [1] NA

最令人费解的是以下这个结果:

1NA == NA

2#> [1] NA

要想理解为什么会这样,最容易的方式是加入一点背景知识:

1# 令x为Mary的年龄。我们不知道她有多大。

2x <- NA

3# 令y为John的年龄。我们不知道他有多大。

4y <- NA

5# John和Mary的年龄是相同的吗?

6x == y

7#> [1] NA

8# 我们不知道!

如果想要确定一个值是否为缺失值,可以使用 is.na() 函数:

1> x <- NA

2> is.na(x)

3[1] TRUE

filter() 只能筛选出条件为 TRUE 的行;它会排除那些条件为 FALSE  NA 的行。如果想保留缺失值,可以明确指出:

1> df <- tibble(x = c(1, NA, 3))

2> filter(df, x > 1)

3# A tibble: 1 x 1

4      x

5  

61     3

7> filter(df, is.na(x) | x > 1)

8# A tibble: 2 x 1

9      x

10  

111    NA

122     3

3.3

使用arrange()排列行

arrange() 函数的工作方式与 filter() 函数非常相似,但前者不是选择行,而是改变行的顺序。它接受一个数据框和一组作为排序依据的列名(或者更复杂的表达式)作为参数。如果列名不只一个,那么就使用后面的列在前面排序的基础上继续排序:

1arrange(flights, year, month, day)

1> arrange(flights, year, month, day)

2# A tibble: 336,776 x 19

3    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

4                                           

5 1  2013     1     1      517            515         2      830            819        11

6 2  2013     1     1      533            529         4      850            830        20

7 3  2013     1     1      542            540         2      923            850        33

8 4  2013     1     1      544            545        -1     1004           1022       -18

9 5  2013     1     1      554            600        -6      812            837       -25

10 6  2013     1     1      554            558        -4      740            728        12

11 7  2013     1     1      555            600        -5      913            854        19

12 8  2013     1     1      557            600        -3      709            723       -14

13 9  2013     1     1      557            600        -3      838            846        -8

1410  2013     1     1      558            600        -2      753            745         8

15# ... with 336,766 more rows, and 10 more variables: carrier , flight ,

16#   tailnum , origin , dest , air_time , distance , hour ,

17#   minute , time_hour 

使用 desc() 可以按列进行降序排序:

1> arrange(flights, desc(arr_delay))

2# A tibble: 336,776 x 19

3    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay

4                                           

5 1  2013     1     9      641            900      1301     1242           1530      1272

6 2  2013     6    15     1432           1935      1137     1607           2120      1127

7 3  2013     1    10     1121           1635      1126     1239           1810      1109

8 4  2013     9    20     1139           1845      1014     1457           2210      1007

9 5  2013     7    22      845           1600      1005     1044           1815       989

10 6  2013     4    10     1100           1900       960     1342           2211       931

11 7  2013     3    17     2321            810       911      135           1020       915

12 8  2013     7    22     2257            759       898      121           1026       895

13 9  2013    12     5      756           1700       896     1058           2020       878

1410  2013     5     3     1133           2055       878     1250           2215       875

15# ... with 336,766 more rows, and 10 more variables: carrier , flight ,

16#   tailnum , origin , dest , air_time , distance , hour ,

17#   minute , time_hour 

缺失值总是排在最后:

1> df <- tibble(x = c(5, 2, NA))

2> arrange(df, x)

3# A tibble: 3 x 1

4      x

5  

61     2

72     5

83    NA

9> arrange(df, desc(x))

10# A tibble: 3 x 1

11      x

12  

131     5

142     2

153    NA

— END —

往期 · 推荐

《R数据科学》学习笔记|Note1:绪论

《R数据科学》学习笔记|Note2:使用ggplot2进行数据可视化(上)

《R数据科学》学习笔记|Note3:使用ggplot2进行数据可视化(下)

零基础"机器学习"自学笔记|Note5:多变量线性回归

零基础"机器学习"自学笔记|Note6:正规方程及其推导(内附详细推导过程)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容