R学习:R for Data Science(五)

R学习:R for Data Science(一)

R学习:R for Data Science(二)

R学习:R for Data Science(三)

R学习:R for Data Science(四)

在R for Data Science(四)中我们学到了第三章,有以下知识点

第3章 使用dplyr进行数据转换

3.1.1 准备工作

3.1.2  nycflights13

3.1.3  dplyr基础

3.2   使用filter()筛选行

3.2.1 比较运算符

3.2.2 逻辑运算符

3.2.3 缺失值

3.3   使用arrange()排列行

3.4   使用select()选择列

3.5   使用mutate()添加新变量

3.5.1 常用创建函数

复习了以上知识点,虽然也没法一次都记住,起码将来需要用到的时候知道在哪里找。下面我们继续

3.6 使用summarize()进行分组摘要

最后一个核心函数是 summarize(),它可以将数据框折叠成一行

summarize(flights, delay = mean(dep_delay, na.rm = TRUE))#> # A tibble: 1 × 1#> delay#> <dbl>#> 1 12.6

如果不与 group_by() 一起使用,那么 summarize() 也就没什么大用。group_by() 可以将分析单位从整个数据集更改为单个分组。接下来,在分组后的数据框上使用 dplyr 函数时,它们会自动地应用到每个分组。例如,如果对按日期分组的一个数据框应用与上面完全相同的代码,那么我们就可以得到每日平均延误时间

by_day <- group_by(flights, year, month, day)summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))#> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day delay#> <int> <int> <int> <dbl>#> 1 2013 1 1 11.55#> 2 2013 1 2 13.86#> 3 2013 1 3 10.99#> 4 2013 1 4 8.95#> 5 2013 1 5 5.73#> 6 2013 1 6 7.15#> # ... with 359 more rows

group_by()和summarize() 的组合构成了使用 dplyr 包时最常用的操作之一

3.6.1 使用管道组合多种操作

%>%叫做管道符,在阅读代码时, %>%最好读作“然后”。

使用这种方法时, x %>% f(y) 会转换为 f(x, y), x %>% f(y) %>% g(z) 会转换为 g(f(x,y), z),以此类推。你可以使用管道重写多种操作,将其变为能够从左到右或从上到下阅读。

3.6.2 缺失值

我们在前面使用了参数 na.rm,你应该非常想要知道其含义。如果没有设置这个参数,会发生什么情况呢?

flights %>%group_by(year, month, day) %>%summarize(mean = mean(dep_delay))#> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day mean#> <int> <int> <int> <dbl>#> 1 2013 1 1 NA#> 2 2013 1 2 NA#> 3 2013 1 3 NA#> 4 2013 1 4 NA#> 5 2013 1 5 NA#> 6 2013 1 6 NA#> # ... with 359 more rows

我们会得到很多缺失值!这是因为聚合函数遵循缺失值的一般规则:如果输入中有缺失值,那么输出也会是缺失值。好在所有聚合函数都有一个 na.rm 参数,它可以在计算前除去缺失值:

flights %>%group_by(year, month, day) %>%summarize(mean = mean(dep_delay, na.rm = TRUE))#> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day mean#> <int> <int> <int> <dbl>#> 1 2013 1 1 11.55#> 2 2013 1 2 13.86#> 3 2013 1 3 10.99#> 4 2013 1 4 8.95#> 5 2013 1 5 5.73#> 6 2013 1 6 7.15#> # ... with 359 more rows

在这个示例中,缺失值表示取消的航班,我们也可以通过先去除取消的航班来解决缺失值问题。保存这个数据集,以便我们可以在接下来的几个示例中继续使用

not_cancelled <- flights %>%filter(!is.na(dep_delay), !is.na(arr_delay))not_cancelled %>% group_by(year, month, day) %>% summarize(mean = mean(dep_delay)) #> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day mean#> <int> <int> <int> <dbl>#> 1 2013 1 1 11.44#> 2 2013 1 2 13.68#> 3 2013 1 3 10.91#> 4 2013 1 4 8.97#> 5 2013 1 5 5.73#> 6 2013 1 6 7.15#> # ... with 359 more rows

3.6.3 计数

聚合操作中包括一个计数(n())或非缺失值的计数(sum(!is_na()))是个好主意。这样你就可以检查一下,以确保自己没有基于非常少量的数据作出结论。例如,我们查看一下具有最长平均延误时间的飞机(通过机尾编号进行识别):

delays <- not_cancelled %>% group_by(tailnum) %>% summarize( delay = mean(arr_delay) )ggplot(data = delays, mapping = aes(x = delay)) + geom_freqpoly(binwidth = 10)

有些飞机的平均延误时间长达 5 小时
我们可以画一张航班数量和平均延误时间的散点图,以便获得更深刻的理解:

delays <- not_cancelled %>% group_by(tailnum) %>% summarize( delay = mean(arr_delay, na.rm = TRUE), n = n() )ggplot(data = delays, mapping = aes(x = n, y = delay)) + geom_point(alpha = 1/10)

结果并不出乎意料,当航班数量非常少时,平均延误时间的变动特别大。
查看此类图形时,通常应该筛选掉那些观测数量非常少的分组,这样你就可以避免受到特别小的分组中的极端变动的影响,进而更好地发现数据模式

3.6.4 常用的摘要函数

只使用均值、计数和求和是远远不够的, R 中还提供了很多其他的常用的摘要函数

位置度量
我们已经使用过 mean(x),但 median(x) 也非常有用。均值是总数除以个数;中位数则是这样一个值:50% 的 x 大于它,同时 50% 的 x 小于它

not_cancelled %>%group_by(year, month, day) %>%summarize(# 平均延误时间:avg_delay1 = mean(arr_delay),# 平均正延误时间:avg_delay2 = mean(arr_delay[arr_delay > 0]))#> Source: local data frame [365 x 5]#> Groups: year, month [?]#>#> year month day avg_delay1 avg_delay2#> <int> <int> <int> <dbl> <dbl>#> 1 2013 1 1 12.65 32.5#> 2 2013 1 2 12.69 32.0#> 3 2013 1 3 5.73 27.7#> 4 2013 1 4 -1.93 28.3#> 5 2013 1 5 -1.53 22.6#> 6 2013 1 6 4.24 24.4#> # ... with 359 more rows

分散程度度量:sd(x)、 IQR(x) 和 mad(x)
均方误差(又称标准误差, standard deviation, sd)是分散程度的标准度量方式。四分位距 IQR() 和绝对中位差 mad(x) 基本等价,更适合有离群点的情况

秩的度量:min(x)、 quantile(x, 0.25) 和 max(x)
分位数是中位数的扩展。例如, quantile(x, 0.25) 会找出 x 中按从小到大顺序大于前25% 而小于后 75% 的值
每天最早和最晚的航班何时出发?

not_cancelled %>%group_by(year, month, day) %>%summarize(first = min(dep_time),last = max(dep_time))#> Source: local data frame [365 x 5]#> Groups: year, month [?]#>#> year month day first last#> <int> <int> <int> <int> <int>#> 1 2013 1 1 517 2356#> 2 2013 1 2 42 2354#> 3 2013 1 3 32 2349#> 4 2013 1 4 25 2358#> 5 2013 1 5 14 2357#> 6 2013 1 6 16 2355#> # ... with 359 more rows

定位度量:first(x)、 nth(x, 2) 和 last(x)
这几个函数的作用与 x[1]、 x[2] 和 x[length(x)] 相同,只是当定位不存在时(比如尝试从只有两个元素的分组中得到第三个元素),前者允许你设置一个默认值。例如,我们可以找出每天最早和最晚出发的航班

not_cancelled %>% group_by(year, month, day) %>% summarize( first_dep = first(dep_time), last_dep = last(dep_time) )

计数

n(),它不需要任何参数,并返回当前分组的大小。如果想要计算出非缺失值的数量,可以使用 sum(!is.na(x))。要想计算出唯一值的数量,可以使用 n_
distinct(x)

哪个目的地具有最多的航空公司?

not_cancelled %>% group_by(dest) %>% summarize(carriers = n_distinct(carrier)) %>%  arrange(desc(carriers))

因为计数太常用了,所以 dplyr 提供了一个简单的辅助函数,用于只需要计数的情况

not_cancelled %>% count(dest) #> # A tibble: 104 × 2#> dest n#> <chr> <int>#> 1 ABQ 254#> 2 ACK 264#> 3 ALB 418#> 4 ANC 8#> 5 ATL 16837#> 6 AUS 2411#> # ... with 98 more rows

你还可以选择提供一个加权变量。例如,你可以使用以下代码算出每架飞机飞行的总里程数(实际上就是求和):

not_cancelled %>% count(tailnum, wt = distance)#> # A tibble: 4,037 × 2#> tailnum n#> <chr> <dbl>#> 1 D942DN 3418#> 2 N0EGMQ 239143#> 3 N10156 109664#> 4 N102UW 25722#> 5 N103US 24619#> 6 N104UW 24616#> # ... with 4,031 more rows

逻辑值的计数和比例:sum(x > 10) 和 mean(y == 0)
当与数值型函数一同使用时, TRUE 会转换为 1, FALSE 会转换为 0。这使得 sum() 和 mean()非常适用于逻辑值:sum(x) 可以找出 x 中 TRUE 的数量, mean(x) 则可以找出比例

多少架航班是在早上5点前出发的?

not_cancelled %>% group_by(year, month, day) %>% summarize(n_early = sum(dep_time < 500))#> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day n_early#> <int> <int> <int> <int>#> 1 2013 1 1 0#> 2 2013 1 2 3#> 3 2013 1 3 4#> 4 2013 1 4 3#> 5 2013 1 5 3#> 6 2013 1 6 2#> # ... with 359 more rows

延误超过1小时的航班比例是多少?

not_cancelled %>% group_by(year, month, day) %>% summarize(hour_perc = mean(arr_delay > 60)) #> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day hour_perc#> <int> <int> <int> <dbl>#> 1 2013 1 1 0.0722#> 2 2013 1 2 0.0851#> 3 2013 1 3 0.0567#> 4 2013 1 4 0.0396#> 5 2013 1 5 0.0349#> 6 2013 1 6 0.0470#> # ... with 359 more rows

3.6.5 按多个变量分组

使用多个变量进行分组时,每次的摘要统计会用掉一个分组变量。这样就可以轻松地对数据集进行循序渐进的分析:

daily <- group_by(flights, year, month, day)(per_day <- summarize(daily, flights = n()))#> Source: local data frame [365 x 4]#> Groups: year, month [?]#>#> year month day flights#> <int> <int> <int> <int>#> 1 2013 1 1 842#> 2 2013 1 2 943#> 3 2013 1 3 914#> 4 2013 1 4 915#> 5 2013 1 5 720#> 6 2013 1 6 832#> # ... with 359 more rows(per_month <- summarize(per_day, flights = sum(flights)))#> Source: local data frame [12 x 3]#> Groups: year [?]#>#> year month flights#> <int> <int> <int>#> 1 2013 1 27004#> 2 2013 2 24951#> 3 2013 3 28834#> 4 2013 4 28330#> 5 2013 5 28796#> 6 2013 6 28243#> # ... with 6 more rows(per_year <- summarize(per_month, flights = sum(flights)))#> # A tibble: 1 × 2#> year flights#> <int> <int>#> 1 2013 336776

在循序渐进地进行摘要分析时,需要小心:使用求和与计数操作是没问题的,但如果想要使用加权平均和方差的话,就要仔细考虑一下,在基于秩的统计数据(如中位数)上是无法进行这些操作的。换句话说,对分组求和的结果再求和就是对整体求和,但分组中位数的中位数可不是整体的中位数。

3.6.6 取消分组

如果想要取消分组,并回到未分组的数据继续操作,那么可以使用ungroup() 函数

daily %>% ungroup() %>% # 不再按日期分组 summarize(flights = n()) # 所有航班#> # A tibble: 1 × 1#> flights#> <int>#> 1 336776

好了,这一章我们就学习完了,虽然很枯燥乏味,不过还是很实用的。

下面是福利专用贴链接,有最近收集的资源,可以打开看看有没有想要的

福利专用贴

(0)

相关推荐