搜索
查看: 1367|回复: 4

[R] 小洁详解《R数据科学》--第三章dplyr

[复制链接]

25

主题

50

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
发表于 2018-9-11 00:07:19 | 显示全部楼层 |阅读模式
本帖最后由 hijack 于 2018-9-11 00:09 编辑

小洁写于2018.9.4


1.准备
(1)准备R包
在《小洁详解<R数据科学>》系列的准备工作中,在安装tidyverse后加载的界面显示了一个冲突,书中对冲突做出的解释在第33页,简单说就是dplyr包覆盖了基础R包中的两个函数,如果你要使用被覆盖的函数,需要输入他们的完整名称,以::连接包名和函数名。




小洁补充:除了conflicts外,R还会返回Warning和error。conflicts和warning一样,是可以视而不见的。
[AppleScript] 纯文本查看 复制代码
install.packages("nycflights13")[/align][align=left]library(nycflights13)library(tidyverse)
(2)准备示例数据
使用nycflights13包的flights作为示例数据。
拿到一个数据首先要观察它。-我忘了谁说的,反正好有道理
那么我仔细端详flights
2013年从纽约市出发的所有336776次航班的信息。
[AppleScript] 纯文本查看 复制代码
flights #就瞅一眼,看看几行几列
?flights #好好瞅瞅每列表示什么意思
View(flights)#以表格的形式好好瞅瞅
class(flights)#了解他的类别
行列数:336,776 x 19
year,month,day -日期
dep_time sched_dep_time 起飞时间 实际/计划
dep_delay 起飞延误时间
arr_time sched_arr_time 到达时间 实际/计划
arr_delay 到达延误时间
carrier 航空公司缩写
flight 航班号
tailnum 飞机尾号
origin/dest 出发地/目的地
air_time 飞行总时间,单位min
distance 出发地和目的地两机场间的距离,单位英里
hour、minute 计划停歇时间
time_hour

补充:变量类型
int -整数
dbl-双精度浮点数、实数
dttm-日期+时间
lgl-逻辑型变量,仅包括TRUE和FALSE
fctr-因子,R中用因子表示具有固定数目的值的分类。
date-日期型变量

(3)dplyr包的核心函数
  • filter 按行筛选
  • arrange 给行排序
  • select 按列筛选
  • mutate 根据原有列生成新列
  • summarize 摘要统计
关于行和列的补充:行=观测,列=变量
2.使用filter()进行行筛选
注意:dplyr函数不修改原数据框,只从原数据框中生成新数据框,如果新生成的数据框不赋值给一个新的变量,那么就会丢失。
R要么输出结果,要么赋值。将赋值语句用括号括起来则可以同时完成这两种操作。
[AppleScript] 纯文本查看 复制代码
filter(flights, month == 1, day == 1) #输出结果jan1 <- filter(flights, month == 1, day == 1) #赋值(dec25 <- filter(flights, month == 12, day == 25))#两种操作
(1)比较运算符
>,>=,<,<=,!= ,==
双精度浮点数用near(a,b)取代a==b
(2)逻辑运算符
布尔运算符号 &|!并、或、非



  • 复杂的筛选条件简化 %in%
[AppleScript] 纯文本查看 复制代码
filter(flights, month == 11 | month == 12)
filter(flights, month %in% c(11, 12))

  • 复杂的筛选条件简化 !
    !(x & y)等价于!x | !y,!(x | y)等价于!x & !y
    tips:括号要从内向外计算
[AppleScript] 纯文本查看 复制代码
filter(flights, !(arr_delay > 120 | dep_delay > 120))
filter(flights, arr_delay <= 120, dep_delay <= 120)
(3)缺失值
NA,表示有一个值,但是不知道具体是啥,相当于个陌生人。而NULL相当于,根本没人。。。
NA与NULL的区分:一个元素值全为NA的向量,它的长度是存在的,就等于元素的个数。而如果把一个向量的所有元素的值都设为NULL,这个向量就变成了“空值”,其长度为0,表明“空无一物”。(出处:Mountain's_blog
[AppleScript] 纯文本查看 复制代码
df <- tibble(x = c(1, NA, 3))
filter(df, x > 1)
filter(df, is.na(x) | x > 1)  #is.na(x)判断是否为缺失值
3.arrange()
[AppleScript] 纯文本查看 复制代码
arrange(flights, year, month, day)
arrange(flights, desc(dep_delay))
无论正序倒序,空值排在最后
[AppleScript] 纯文本查看 复制代码
df <- tibble(x = c(5, 2, NA))
arrange(df, x)
arrange(df, desc(x))
如果要将NA排在最前面,则需要使用
[AppleScript] 纯文本查看 复制代码
arrange(flights, desc(is.na(dep_time)), dep_time)
关于3.3的练习
(2)对比了一下中英文的问题和答案,感觉“出发时间最早”,作者想表达的可能是提前出发时间最长的(比如有一班提前43分钟飞走的,恕我孤陋寡闻不知道有这种操作啊),而不是半夜12点起飞的。有点歧义。
(3)fastest,我以为要距离除以飞行时间这样算。我认为应该是
[AppleScript] 纯文本查看 复制代码
mutate(flights,vic=distance/air_time) %>%arrange(desc(vic)) %>%select(year,month,day,vic,everything())

结果给出的答案是飞行时间最短的,应该是不严谨,欢迎发表不同意见。
(4)第四题英文原文说的是Which flights traveled the longest? Which traveled the shortest?
中文书籍翻译为飞行时间最长、最短,英文答案则认为是距离最长、最短,这个歧义也是哈哈。没有什么深究的意义,个人偏向于距离,至于真正表达的意思应该只有hadley大神自己清楚了。
4.select()按列筛选
[AppleScript] 纯文本查看 复制代码
#1. 根据列名单独选择某几列[/align][align=left]select(flights, year, month, day)[/align][align=left]#2.连选几列[/align][align=left]select(flights, year:day)[/align][align=left]#3.连选+反选[/align][align=left]select(flights, -(year:day))[/align][align=left]#4.辅助函数-选择列名符合以下要求的[/align][align=left]starts_with("abc"): 以abc开头的[/align][align=left]ends_with("xyz"): 以xyz结尾的[/align][align=left]contains("ijk"):包含ijk的[/align][align=left]matches("(.)\\1"): 匹配正则表达式的[/align][align=left]#5.重命名[/align][align=left]rename(flights, tail_num = tailnum) [/align][align=left]#将tailnum修改为tail_name[/align][align=left]#6.某几列移动到开头,everything表示其余各列[/align][align=left]select(flights, time_hour, air_time, everything())
p42练习
-------------------------------------------------(我又偷窥答案了)-------------------------------------------------------------
(2)select()函数多次计入一个变量名,会自动去重复,只保留第一次。
(3)one_of()
[AppleScript] 纯文本查看 复制代码
vars <- c("year", "month", "day", "dep_delay", "arr_delay")
select(flights, one_of(vars))

var是character vector(特征向量),这样写出的select()只不必写多个向量名。
(4)select辅助函数默认忽略大小写,如需修改:
[AppleScript] 纯文本查看 复制代码
select(flights, contains("TIME", ignore.case = FALSE))
5.mutate() 生成新列
mutate和transmute的区别:mutate生成新列后,添加新列到数据框末尾,生成新数据框。transmute则是只保留新生成的列。这里说的是生成,是指原有列加减乘除等计算出的结果作为新列。
生成新列gain和speed:
[AppleScript] 纯文本查看 复制代码
flights_sml <- select(flights,   year:day,   ends_with("delay"),   distance,   air_time)
mutate(flights_sml,  gain = dep_delay - arr_delay,  speed = distance / air_time * 60)

新列可以直接参与另一新列的生成,原文“一旦创建,新列就可以立即使用”。这里指的是可以根据新列进行新的计算,再生成新列。
[AppleScript] 纯文本查看 复制代码
mutate(flights_sml,  gain = dep_delay - arr_delay,  hours = air_time / 60,  gain_per_hour = gain / hours)

transmute():只保留新列。
[AppleScript] 纯文本查看 复制代码
transmute(flights,  gain = dep_delay - arr_delay,  hours = air_time / 60,  gain_per_hour = gain / hours)


mutate常用创建函数

6.使用summarize()进行分组摘要
其实应该是使用group_by和summarize()进行分组摘要。如果没有group_by,就会把整个数据框作为一个整体,会变成一行。
书中的代码中有na.rm = TRUE,删掉的话会变成:




group_by函数会使summarise更有用。按照某列来分组,分别汇总摘要。
ex:计算每天的平均延误时间
[AppleScript] 纯文本查看 复制代码
by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))
(1)管道操作
管道操作会简化代码,数据框名不必重复写多次。
[AppleScript] 纯文本查看 复制代码
#level一-生成中间产物,不喜欢
by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))
#level二-这个是我习惯的方式summarise(group_by(flights, year, month, day), delay = mean(dep_delay, na.rm = TRUE))
#level三-管道操作连接两步,数据框名在括号里面
group_by(flights, year, month, day) %>% summarise(delay = mean(dep_delay, na.rm = TRUE))
#level四-管道操作连接两步,数据框名在括号里面
flights %>%group_by( year, month, day) %>% summarise(delay = mean(dep_delay, na.rm = TRUE))

完成数据准备需要分组--摘要统计--筛选。
管道操作连接多行命令时,将管道符号%>%放在上一行末尾。
(2)缺失值
上面提到,代码中有na.rm = TRUE,删掉的话会变成:




这是因为缺失值会“传染”,也就是说用于计算平均值的数中有空值,那么结果就是空值。
下面这个例子也是一样,分组后计算出的dep_delay仍然都是空值。
[AppleScript] 纯文本查看 复制代码
flights %>%   group_by(year, month, day) %>%   summarise(mean = mean(dep_delay))



na.rm = TRUE这个参数会在计算前移除缺失值。
[AppleScript] 纯文本查看 复制代码
flights %>%   group_by(year, month, day) %>%   summarise(mean = mean(dep_delay, na.rm = TRUE))

移除后计算的方法,还可以用filter筛出非空行列,再行计算。(笨办法)
[AppleScript] 纯文本查看 复制代码
not_cancelled <- flights %>%   filter(!is.na(dep_delay), !is.na(arr_delay))not_cancelled %>%   group_by(year, month, day) %>%   summarise(mean = mean(dep_delay))
(3)计数
示例:找出平均延误时间最长的飞机
(根据tailname进行分组,得到的时全年同一架飞机的各种数据)
补充:关于count()和n()的探索:统计每个航空公司各有多少趟航班
[AppleScript] 纯文本查看 复制代码
  carriers <- group_by(flights, carrier)  
s1 <- summarise(carriers, n())   
s2 <- count(flights,carrier)  
mu <- mutate(carriers, n = n()) 
 s3 <- distinct(mu,n)  
s4 <- distinct(mu,carrier,n)

四种方法统计的结果是一致的,distinct是去重复。
(4)常用的摘要函数


(5)按多个变量分组
(其实表达的意思是 多级分组)
[AppleScript] 纯文本查看 复制代码
#先按照年月日分组,也就是按天
daily <- group_by(flights, year, month, day)
(per_day   <- summarise(daily, flights = n()))
#再按照月份汇总摘要
(per_month <- summarise(per_day, flights = sum(flights)))
#再按年汇总,只有一年的数据所以成了一行
(per_year  <- summarise(per_month, flights = sum(flights)))
(6)取消分组 ungroup
也就是说将分好组的数据框可逆返回到原始数据。
[AppleScript] 纯文本查看 复制代码
daily %>%   ungroup() %>%             # no longer grouped by date  
summarise(flights = n())  # all flights
7.分组新变量
(1)找出每个分组中最差的成员
原文“找出每个分组中最差的成员”在例子中,是选择每天延误时间最长的10趟航班
[AppleScript] 纯文本查看 复制代码
flights_sml %>%   group_by(year, month, day) %>%  
filter(rank(desc(arr_delay)) < 10)
(2)找出(数量)大于某个阈值的所有分组
找出最受欢迎的目的地,也就是dest中出现次数高的(高于阈值365)。
思路是;分组,计数,筛选
[AppleScript] 纯文本查看 复制代码
popular_dests <- flights %>%   group_by(dest) %>%  
 filter(n() > 365)
(3)对数据进行标准化以计算分组指标
例:筛选延误的航班,计算各航班的延误时间占目的地总延误时间的比例,并显示指定列。
[AppleScript] 纯文本查看 复制代码
popular_dests %>%   filter(arr_delay > 0) %>%   
mutate(prop_delay = arr_delay / sum(arr_delay)) %>%   
select(year:day, dest, arr_delay, prop_delay)



上一篇:9-10 R数据科学
下一篇:StaQuest第一讲
回复

使用道具 举报

31

主题

36

帖子

1114

积分

金牌会员

Rank: 6Rank: 6

积分
1114
发表于 2018-9-29 19:03:53 | 显示全部楼层
学习了 很好的笔记 赞
回复 支持 反对

使用道具 举报

6

主题

11

帖子

105

积分

注册会员

Rank: 2

积分
105
发表于 2018-10-8 14:26:47 | 显示全部楼层
学习了,仔细研读
回复 支持 反对

使用道具 举报

25

主题

50

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
 楼主| 发表于 2018-10-18 10:41:20 | 显示全部楼层
Lespremeto 发表于 2018-9-29 19:03
学习了 很好的笔记 赞

谢谢 一起进步
回复 支持 反对

使用道具 举报

25

主题

50

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
 楼主| 发表于 2018-10-18 10:42:33 | 显示全部楼层
xray19 发表于 2018-10-8 14:26
学习了,仔细研读

加油加油
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|生信技能树 ( 粤ICP备15016384号  

GMT+8, 2019-10-14 22:11 , Processed in 0.060570 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.