参考:
- 《R数据科学》
- 小洁详解《R数据科学》–第九章 dplyr处理关系
第9章 dplyr处理关系数据
写在前面——plyr包 join()函数
join(x = ,y = ,by=NULL,type="left",match="all")
作用:连接两个数据框,和SQL中连接方式一样,
包括内连接(inner-交集)和外连接(左连接left、右连接right、全连接full)
参数:
- x,y 是两个数据框;
- by 是指定要联合的变量,默认值为所有的变量;
- type 是指定联合的方式(inner、left、right、full)
————————————————
与merge()函数对比,join()函数运行速度比较快
#内连接
merge(x = ,y = ,by = )
#左连接
merge(x = ,y = ,all.x=TRUE,by = )
#右连接
merge(x = ,y = ,all.y=TRUE,by = )
#全连接
merge(x = ,y = ,all.x=TRUE,all.y=TRUE,by = )
————————————————
dplyr中关系连接
- inner 交集
- left_join——x表结构不变
- right _join——y表结构不变
- full_join——并集
1.简介
• 合并连接:向数据框中加入新变量,新变量的值是另一个数据框中的匹配观测。
• 筛选连接:根据是否匹配另一个数据框中的观测,筛选数据框中的观测。
• 集合操作:将观测作为集合元素来处理
2.nycflights13
除了flight外,还有另外四个相关数据框。分别描述航空公司、机场、飞机、天气。
我喜欢以标准表格的形式观察每个数据框。
library(tidyverse)
library(nycflights13)
View(airlines)
View(airports)
View(planes)
View(weather)
- flights 与 planes 通过单变量 tailnum 相连;
- flights 与 airlines 通过变量 carrier 相连;
- flights 与 airports 通过 origin 和 dest、faa相连;
- flights 与 weather 通过变量 origin(位置)以及 year、month、day 和 hour(时间)相连
3.键
用于连接每对数据表的变量称为键。键是能唯一标识观测的变量(或变量集合)。
主键:唯一标识其所在数据表中的观测。例如,planes$tailnum 是一个主键,因为其可
以唯一标识planes 表中的每架飞机。
外键:唯一标识另一个数据表中的观测。例如,flights$tailnum 是一个外键,因为其
出现在flights 表中,并可以将每次航班与唯一一架飞机匹配。
验证主键能否真正唯一标识每个观测。
(这句话的意思相当于检测这个主键能否起到和行号一样的作用,强调唯一)
主键就是女神表中id,外键就是女神表中boyfriend_id
主键与另一张表中的外键可以构成关系
看个例子
beauty表
boys表
左连接
SELECT b.`id`,`name`,`boyfriend_id`,bo.*
FROM `beauty` AS b
LEFT JOIN `boys` AS bo
ON b.`boyfriend_id`=bo.`id`;
结果
练习
(1) 向flights 添加一个代理键。
可以使用muteta()或者row_number()函数生成一个代理键
flights %>%
arrange(year, month, day, sched_dep_time, carrier, flight) %>%
mutate(flight_id = row_number()) %>%
4.合并连接
简化 flights ==》flights2
flights2 <- flights %>%
select(year:day, hour, origin, dest, tailnum, carrier)
View(flights2)
将航空公司全名加入flights2 ==》flights3
view(airlines)
flight3<-flights2 %>%
select(-origin, -dest) %>%
left_join(airlines, by = "carrier")
View(flights3)
#等同于
flights2 %>%
select(-origin, -dest) %>%
mutate(name = airlines$name[match(carrier, airlines$carrier)])#R取子集
注意:left_join和其他的dplyr操作一样,不改变原来的数据框,如果不给它赋值,就只是在控制台展示一下,雁过无痕。所以在这里我给它赋值为flights3。
(1)内连接 inner_join
取交集,未匹配到的行会被丢弃。
内连接最重要的性质是,没有匹配的行不会包含在结果中。这意味着内连接一般不适合在分析中使用,因为太容易丢失观测了。
(2)外连接——不会丢失行
- letf_join左连接:保留第一个数据框X的所有观测。(最常用)
- right_join右连接:保留第二个数据框Y中的所有观测
- full_join全连接:保留两个数据框中的所有观测(并集)。
(3)重复键
连接时会得到所有的组合,通常意味着出现错误。
当连接这样的重复键时,你会得到所有可能的组合,即笛卡儿积:
(4)定义键列
连接时,会自动寻找两个数据框中共有的列作为键来进行匹配(自然连接默认值by=NULL——笛卡尔积),也可自行指定键列
flights2 %>%
left_join(weather)
flights2 %>%
left_join(planes, by = "tailnum")
注意
(1)by = NULL——默认值、自然连接、笛卡尔积
(2)by = “key”——只使用公共变量
(3)by = c(“a”=“b”)——连接字段名称不一样
这种方式会匹配x表中的a变量和y表中的b变量。
输出结果中使用的是x表中的变量。
例如SQL
ON b.`boyfriend_id`=bo.`id`;
flights2%>%
left_join(airports,c("dest"="faa"))
5.筛选连接
-
semi_join(x, y)半连接:不添加新列,保留x表中那些可以匹配y表的行
重要的是存在匹配,匹配了哪条观测则无关紧要。这说明筛选连接不会像合并连接那样造成重复的行。
对数据表进行筛选或摘要统计后,如果想要使用表中原来的行来匹配筛选或摘要结果,那么半连接是非常有用的。 -
anti_join(x, y)反连接:半连接的逆操作是反连接。反连接保留x表中那些没有匹配到 y 表的行。
反连接可以用于诊断连接中的不匹配。找出没有匹配到的行
6.问题
(1)找出主键
(2)主键不能有缺失值
(3)检查外键是否与另一张表的主键相匹配(anti_join)
7.集合
集合操作需要x和y具有相同的列名,并将行按照集合来处理。
intersect(x, y)
返回既在x 表,又在y 表中的观测。
union(x, y)
返回x 表或y 表中的唯一观测。
setdiff(x, y)
返回在x 表,但不在y 表中的观测。
集合跟连接的区别是:
- 用于求集合的列名全都相同,求集合不改变列数,改变行数。
- 用于做连接的列名只有部分一到几列相同,做连接增加列数。