【学习笔记】R数据科学(R for Data Science)—第3章 使用dplyr进行数据转换

dplyr包是tidyverse中的一个核心R包。

dplyr的5个核心函数:

  • 按值筛选观测(filter())
  • 对行进行重新排序(arrange())
  • 按名称选取变量(select())
  • 使用现有变量的函数创建新变量(mutate())
  • 将多个值总结为一个摘要统计量(summarize())

nycflights13 :: flights这个数据框包含了2013年从纽约市出发的所有336776次航班的信息。

View(flights) 可以在RStudio查看器中看到整个flights数据集。

比较运算符

比较运算符:>, >=, <, <=, !=(不等于)和 ==(等于)

逻辑运算符

①布尔运算符:&表示“与”,| 表示“或”,! 表示“非”。
② x %in% y:会选取出x是y中的一个值时的所有行。
③使用德摩根定律:!(x & y)等价于!x | !y、!(x | y)等价于!x & !y。

缺失值

缺失值NA,not available。
如果运算中包含了NA,那么运算结果一般来说也是NA。
is.na()函数可以判断一个值是否为NA。
na.rm():除去缺失值
filter()函数只能筛选出条件为TRUE的行,它会排除那些条件为FALSE和NA的行。

arrange()

改变行的顺序,接受一个数据框和一组作为排序依据的列名(或者更复杂的表达式)作为参数。如果列名不止一个,就使用后面的列在前面排序的基础上继续排序。

desc()

按列进行降序排序

select()

快速生成一个有用的变量子集。

可以在select()函数中使用一些辅助函数:

  • starts_with(“abc”):匹配以abc开头的名称
  • ends_with(“xyz”):匹配以xyz结尾的名称
  • contains(“ijk”):匹配包含ijk的名称
  • matches("(.)\1"):选择匹配正则表达式的变量
  • num_range(“x”, 1:3):匹配x1,x2和x3

用rename()函数来重命名变量能保留所有未明确提及的变量。

mutate()

将新列添加在数据集的最后。

一旦创建,新列就可以立即使用。

算数运算符

+, -, *, /, ^

模运算符

%/%(整除触发), %%(求余)

对数函数

log(), log2(), log10()

偏移函数

lead()和lag()函数可以返回一个序列的领先值和滞后值。他们可以计算出序列的移动差值或发现序列何时发生了变化。

累加和滚动聚合

累加和、累加积、累加最小数、累加最大值、累加均值:cumsum(), cumprod(), cummin(), cummax(), cummean()。

逻辑比较

<, <=, >, >=, !=

排秩

min_rank():可以完成最常用的排秩任务。默认的排秩方式是,最小的值获得最前面的名次,使用desc(x)可以让最大的值获得最前面的名次。
min_rank()的变体:row_number(), dense_rank(), percent_rank(), cume_dist(), ntile()。

分组

summarize()

  • 可以将数据框折叠成一行。
  • 需要和group_by()配合使用。group_by()将分析单位从整个数据集更改为单个分组。在分组后的数据框上使用dplyr函数时,它们会自动地应用到每个分组。

ungroup():取消分组。

group_by()和summarize()的组合构成了使用dplyr包时最常用的操作之一:分组摘要。
虽然与summarize()函数结合起来使用是最有效的,但分组也可以与mutate()和filter()函数结合,以完成非常便捷的操作。

管道(%>%)

管道可以显著提高代码的可读性
x %>% f(y)会转换为f(x,y);x %>% f(y) %>% g(z)会转换为g(f(x,y),z),以此类推。

计数

n(x):不需要任何参数,并返回当前分组的大小
sum(!is_na(x)):计算出非缺失值的数量
n_distinct(x):计算出唯一值的数量
count():如not_cancelled %>% count(dest)
逻辑值的计数和比例:sum(x > 10), mean(y == 0)。当与数值型函数一同使用时,TRUE会转换为1,FALSE会转换为0。这使得sum()和mean()非常适用于逻辑值,sum(x)可以找出x中TRUE的数量,mean(x)可以找出比例。

摘要函数

位置度量:mean(x)(均值), median(x)(中位数)
分散程度度量:sd(x)(均方误差), IQR(x)(四分位距),mad(x)(绝对中位差)。(四分位距和绝对中位差基本等价,更适合有离群点的情况)
秩的度量:min(x), quantile(x,0.25)(分位数,是中位数的扩展,例如quantile(x,0.25)会找出x中按从小到大顺序大于前25%而小于后75%的值), max(x)
定位度量:first(x), nth(x,2), last(x)

练习题

3.2.4

(1)找出满足以下条件的所有航班。

a.到达时间延误2小时或更多的航班。

library(nycflights13)
filter(flights, arr_delay >= 120)

b.飞往休斯顿(IAH机场或HOU机场)的航班。

filter(flights, dest == "IAH" | dest == "HOU")

filter(flights, dest %in% c("IAH", "HOU"))

c.由联合航空(United)、美利坚航空(American)或三角洲航空(Delta)运营的航班。

filter(flights, carrier == "UA" | carrier == "AA" | carrier == "DL")

filter(flights, carrier %in% c("UA", "AA", "DL"))

d.夏季(7、8、9月)出发的航班。

filter(flights, month == 7 | month == 8 | month == 9)

filter(flights, month %in% c(7, 8, 9))

filter(flights, month %in% c(7:9)) # filter(flights, month %in% 7:9)

e.到达时间延误超过2小时,但出发时间没有延误的航班。

filter(flights, arr_delay >= 120 & dep_delay <= 0)

f.延误至少1小时,但飞行过程弥补回30分钟的航班。

filter(flights, dep_delay >= 60 & arr_delay == dep_delay - 30)

g.出发时间在午夜和早上6点之间(包括0点和6点)的航班。

filter(flights, dep_time >= 000 & dep_time <= 600)

(2)dplyr中对筛选有帮助的另一个函数是between()。它的作用是什么?你能使用这个函数来简化解决前面问题的代码吗?

在这里插入图片描述

# d
filter(flights, between(month, 7, 9))

# g
filter(flights, between(dep_time, 000, 600))

(3)dep_time有缺失值的航班有多少?其他变量的缺失值情况如何?这样的行表示什么情况?

result <- filter(flights, is.na(dep_time))
nrow(result)
head(result)

在这里插入图片描述
到达时间也是NA,有可能是这些航班被取消了。

(4)为什么NA ^ 0的值不是NA?为什么NA | TRUE的值不是NA?为什么FALSE & NA的值不是NA?

在这里插入图片描述所有数字的0次方是1,“或”有真为真,“和”有假为假。

3.3

(1)如何使用arrange()将缺失值排在最前面?

df <- tibble(x = c(5, 2, NA))
df
arrange(df, desc(is.na(x)))

在这里插入图片描述

head(arrange(flights, desc(is.na(dep_delay)), dep_delay))

在这里插入图片描述

(2)对flights排序以找出延误时间最长的航班。找出出发时间最早的航班。

# 找出延误时间最长的航班
head(arrange(flights, desc(dep_delay)),1)

# 找出出发时间最早的航班
head(arrange(flights, dep_delay), 1)

在这里插入图片描述在这里插入图片描述

(3)对flights排序以找出速度最快的航班。

head(arrange(flights, desc(distance / air_time), 1))

![在这里插入图片描述](https://img-blog.csdnimg.cn/0ce3f1aa813f4a3c9023365905e6e8ed.png

(4)哪个航班的飞行时间最长?哪个最短?

在这里插入图片描述在这里插入图片描述

3.4

(1)从flights数据集中选择dep_time、dep_delay、arr_time和arr_delay,通过头脑风暴找出尽可能多的方法。

select(flights, dep_time, dep_delay, arr_time, arr_delay)

在这里插入图片描述

select(flights, c("dep_time", "dep_delay", "arr_time", "arr_delay"))

在这里插入图片描述

select(flights, any_of(c("dep_time", "dep_delay", "arr_time", "arr_delay")))

在这里插入图片描述

(2)如果在select()函数中多次计入一个变量名,那么会发生什么情况?

select(flights, dep_time, dep_time, dep_time)

在这里插入图片描述

(3)one_of()函数的作用是什么?为什么它结合以下向量使用时非常有用?

vars <- c("year", "month", "day", "dep_delay", "arr_delay")

在这里插入图片描述

vars <- c("year", "month", "day", "dep_delay", "arr_delay")
vars
select(flights, one_of(vars))

在这里插入图片描述

(4)以下代码的运行结果是否出乎意料?选择辅助函数处理大小写的默认方式是什么?如何改变默认方式?

select(flights, contains("TIME"))

在这里插入图片描述选择辅助函数处理大小写的默认方式是TRUE。

select(flights, contains("TIME", ignore.case = FALSE))

在这里插入图片描述

3.5.2

(1)虽然现在的dep_time和sched_dep_time变量方便阅读,但不适合计算,因为它们实际上并不是连续型数值。将它们转换成一种更方便的表示形式,即从午夜开始的分钟数。

flights_ <- mutate(flights, 
                   dep_time_min = (dep_time %/% 100 * 60 + dep_time %% 100) %% 1440,
                   sched_dep_time_min = (sched_dep_time %/% 100 * 60 + sched_dep_time %% 100) %% 1440)

# 为避免代码冗余,构建一个函数:
time2min <- function(x){
  (x %/% 100 * 60 + x %% 100) %% 1440
}

flight_new <- mutate(flights,
                     dep_time_min = time2min(dep_time),
                     sched_dep_time_min = time2min(sched_dep_time))

这题不明白,在http://www.360doc.com/content/20/1109/23/71039787_945054327.shtml看的答案。

(2)比较air_time和arr_time - dep_time。你期望看到什么?实际又看到了什么?如何解决这个问题?

在这里插入图片描述

a <- mutate(flights,  air = (arr_time - dep_time))
a
select(a, air)

在这里插入图片描述
期望看到air_time 和 arr_time - dep_time的值相同,实际上air_time小于arr_time - dep_time,原因是air_time不包括飞机在地面的滑行时间,仅仅指从起飞到进入着陆之间的时间。

(3)比较dep_time, sched_dep_time和dep_delay。你期望这3个数值之间具有何种关系?

期望:dep_time - sched_dep_time = dep_delay

(4)使用排秩函数找出10个延误时间最长的航班。如何处理名次相同的情况?仔细阅读min_rank()的帮助文件。

head(arrange(mutate(flights, delay_rank = min_rank(dep_delay)), desc(delay_rank)), 10)

在这里插入图片描述

(5)1:3 + 1:10会返回什么?为什么?

在这里插入图片描述

(6)R提供了哪些三角函数?

在这里插入图片描述

3.6.7

(1)通过头脑风暴,至少找出5种方法来确定一组航班的典型延误特征。思考以下场景:

  • 一架航班50%的时间会提前15分钟,50%的时间会延误15分钟。
  • 一架航班总是会延误10分钟。
  • 一架航班50%的时间会提前30分钟,50%的时间会延误30分钟。
  • 一架航班99%的时间会准时,1%的时间会延误2个小时。
    哪一种更重要?到达延误还是出发延误?

到达延误更重要。

(2)找出另外一种方法,这种方法要可以给出与not_cancelled %>% count(dest)和not_cancelled %>% count(tailnum, wt = distance)同样的输出(不能使用count())。

# Method 1
not_cancelled %>%
  count(dest)

# Method 2  
not_cancelled %>%
  group_by(dest) %>%
  summarize(n = length(dest))

# Method 3 
not_cancelled %>%
  group_by(dest) %>%
  summarize(n = n())

在这里插入图片描述

# Method 1
not_cancelled %>%
  count(tailnum, wt = distance)

# Method 2
not_cancelled %>%
  group_by(tailnum) %>%
  summarize(n = sum(distance))

在这里插入图片描述

(3)我们对已取消航班的定义(is.na(dep_delay)) | (is.na(arr_delay))稍有欠佳。为什么?哪一列才是最重要的?

影响arr_delay的因素有很多,有可能是飞机没有起飞,也可能是飞机遇到突发情况在其他机场降落。

(4)查看每天取消的航班数量。其中存在模式吗?已取消航班的比例与平均延误时间有关系吗?

在这里插入图片描述在这里插入图片描述
这题答案来源→https://cloud.tencent.com/developer/article/1810872

(5)哪个航空公司的延误情况最严重?挑战:你能否分清这个是由于糟糕的机场设备,还是航空公司的问题?为什么能?为什么不能?(提示:考虑一下flights %>% group_by(carrier, dest)%>% summarize(n())。)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

这题答案来源于→https://cloud.tencent.com/developer/article/1810872

(6)计算每架飞机在第一次延误超过1小时前的飞行次数。

(7)count()函数中的sort参数的作用是什么?何时应该使用这个参数?

在这里插入图片描述

3.7

(1)查看常用的新变量函数和筛选函数的列表。当它们与分组操作结合使用时,功能有哪些变化?
(2)哪一架飞机(用机尾编号来识别,tailnum)具有最差的准点记录?
(3)如果想要尽量避免航班延误,那么应该在一天中的那个时间搭乘飞机?
(4)计算每个目的地的延误总时间的分钟数,以及每架航班到每个目的地的延误时间比例。
(5)延误通常是由临时原因造成的:即使最初引起延误的问题已经解决,但因为要让前面的航班先起飞,所以后面的航班也会延误。使用lag()函数探究一架航班延误与前一架航班延误之间的关系。
(6)查看每个目的地。你能否发现有些航班的速度快得可疑?(也就是说,这些航班的数据可能是错误的。)计算出目的地的最短航线的飞行时间。哪架航班在空中的延误时间最长?
(7)找出至少有两个航空公司的所有目的地。使用数据集中的信息对航空公司进行排名。

  • 28
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谙隅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值