dplyr包处理关系数据(键、内连接、外连接、筛选连接、集合操作)

使用dplyr处理关系数据

使用 dplyr 的一些函数来研究一下 nycflights13 中的关系数据,这些函数可以在两张数据表间进行操作。

library(tidyverse)

library(nycflights13)

1.2 nycflights13

nycflights13 中包含了与 flights 相关的 4 tibble

(1) airlines:可以根据航空公司的缩写码查到公司全名。

airlines

 

2airports:给出了每个机场的信息,通过 faa 机场编码进行标识。

airports

 

3planes:给出了每架飞机的信息,通过 tailnum 进行标识。

planes

 

4weather:给出了纽约机场每小时的天气状况。

weather

 

对于 nycflights13 包中的表来说:

• flights planes 通过单变量 tailnum 相连;

• flights airlines 通过变量 carrier 相连;

• flights airports 通过两种方式相连(变量 origin dest);

• flights weather 通过变量 origin(位置)以及 yearmonthday hour(时间)相连。

1.3 键

键的类型有两种。

主键:唯一标识其所在数据表中的观测。例如,planes$tailnum 是一个主键,因为其可

以唯一标识 planes 表中的每架飞机。

外键:唯一标识另一个数据表中的观测。例如,flights$tailnum 是一个外键,因为其出现在 flights 表中,并可以将每次航班与唯一一架飞机匹配。

一旦识别出表的主键,最好验证一下,看看它们能否真正唯一标识每个观测。一种验证方

法是对主键进行 count() 操作,然后查看是否有 n 大于 1 的记录:

planes %>%

 count(tailnum) %>%

 filter(n > 1)

 

weather %>%

 count(year, month, day, hour, origin) %>%

 filter(n > 1)

 

flights %>%

 count(year, month, day, flight) %>%

 filter(n > 1)

 

flights %>%

 count(year, month, day, tailnum) %>%

 filter(n > 1)

 

如果一张表没有主键,有时就需要使用 mutate() 函数和 row_number() 函数为表加上一个主键

1.4 合并连接

合并连接可以将两个表格中的变量组合起来,它先通过两个表格的键匹配观测,然后将一个表格中的变量复制到另一个表格中。和 mutate() 函数一样,连接函数也会将变量添加在表格的右侧,因此如果表格中已经有了很多变量,那么新变量就不会显示出来。

flights2 <- flights %>%

 select(year:day, hour, origin, dest, tailnum, carrier)

flights2

 

假设想要将航空公司的全名加入 flights2 数据集,你可以通过 left_join() 函数组合airlines flights2 数据框:

flights2 %>%

  select(-origin, -dest) %>%   #负号表示不选择origin和dest

  left_join(airlines, by = "carrier")

 

1.4.1 理解连接

x <- tribble(

 ~key, ~val_x,

 1, "x1",

 2, "x2",

 3, "x3"

)

y <- tribble(

 ~key, ~val_y,

 1, "y1",

 2, "y2",

 4, "y3"

)

 

1.4.2 内连接

内连接是最简单的一种连接。只要两个观测的键是相等的,内连接就可以匹配它们。

x %>%

inner_join(y, by = "key")

 

1.4.3 外连接

外连接有 3 种类型。

左连接:保留 x 中的所有观测。

右连接:保留 y 中的所有观测

全连接:保留 x y 中的所有观测。

最常用的连接是左连接:只要想从另一张表中添加数据,就可以使用左连接,因为它会保

留原表中的所有观测,即使它没有匹配。

 

1.4.4 重复键

x <- tribble(

 ~key, ~val_x,

 1, "x1",

 2, "x2",

 2, "x3",

 1, "x4"

)

y <- tribble(

 ~key, ~val_y,

 1, "y1",

 2, "y2"

)

     

left_join(x, y, by = "key")

 

1.4.5 定义键列

两张表都是通过一个单变量来连接的,这种限制条件是通过 by = "key" 来实现的。默认值 by = NULL。这会使用存在于两个表中的所有变量,这种方式称为自然连接。

flights2 %>%

 left_join(weather)

 

字符向量 by = "x"。这种方式与自然连接很相似,但只使用某些公共变量。

flights2 %>%

 left_join(planes, by = "tailnum")

 

命名字符向量 by = c("a" = "b")。这种方式会匹配 x 表中的 a 变量和 y 表中的 b 变量。

输出结果中使用的是 x 表中的变量。

因为每次航班都有起点机场和终点机场,所以需要指定使用哪个机场进行连接:

flights2 %>%

 left_join(airports, c("dest" = "faa"))

 

flights2 %>%

 left_join(airports, c("origin" = "faa"))

 

1.5 筛选连接

筛选连接有两种类型。

• semi_join(x, y):保留 x 表中与 y 表中的观测相匹配的所有观测。

• anti_join(x, y):丢弃 x 表中与 y 表中的观测相匹配的所有观测。

假设你已经找出了最受欢迎的前 10 个目的地:

top_dest <- flights %>%

 count(dest, sort = TRUE) %>%

 head(10)

top_dest

 

现在想要找出飞往这些目的地的所有航班,你可以自己构造一个筛选器:

flights %>%

 filter(dest %in% top_dest$dest)

 

使用半连接,它可以像合并连接一样连接两个表,但不添加新列,而是保留 x表中那些可以匹配 y 表的行:

flights %>%

 semi_join(top_dest)

 

反连接可以用于诊断连接中的不匹配。例如,在连接 flights planes 时,你可能想知道

flights 中是否有很多行在 planes 中没有匹配记录:

flights %>%

  anti_join(planes, by = "tailnum") %>%

  count(tailnum, sort = TRUE)

 

1.7 集合操作

集合操作需要 x y 具有相同的变量,并将观测按照集合来处理。

intersect(x, y)  返回既在 x 表,又在 y 表中的观测。

union(x, y)  返回 x 表或 y 表中的唯一观测。

setdiff(x, y)  返回在 x 表,但不在 y 表中的观测。

df1 <- tribble(

 ~x, ~y,

 1, 1,

 2, 1

)

df2 <- tribble(

 ~x, ~y,

 1, 1,

 1, 2

)

   

intersect(df1, df2)

 

union(df1, df2)

 

setdiff(df1, df2)

 

setdiff(df2, df1)

 

posted @ 2021-11-19 13:59  zhang-X  阅读(358)  评论(0)    收藏  举报