在实际应用中,我们常会涉及到多个数据表,必须综合使用它们才能找到关键信息。存在于多个表中的这种数据统称为关系数据。本章中的很多概念都和SQL中的相似,只是在dplyr中的表达形式略微不同。一般来说,dplyr 要比 SQL 更容易使用。
处理关系数据有三类操作:
我们将使用 nycflights13 包来学习关系数据。nycflights13 中包含了与 flights 相关的 4 个 tibble:
数据表 | 信息 |
---|---|
airlines | 可以根据航空公司的缩写码查到公司全名。 |
airports | 给出了每个机场的信息,通过 faa 机场编码进行标识。 |
planes | 给出了每架飞机的信息,通过 tailnum 进行标识。 |
weather | 给出了纽约机场每小时的天气状况。 |
各数据表之间的关系如下:
对于 nycflights13 包中的表来说:
用于连接每对数据表的变量称为键。键是能唯一标识观测的变量(或变量集合)。
键的类型有两种。
一个变量既可以是主键,也可以是外键。例如,origin 是 weather 表主键的一部分,同时 也是 airports 表的外键。一旦识别出表的主键,最好验证一下,看看它们能否真正唯一标识每个观测。一种验证方 法是对主键进行 count() 操作,然后查看是否有 n 大于 1 的记录:
planes %>%
count(tailnum) %>%
filter(n > 1)
#> # A tibble: 0 × 2
#> # ... with 2 variables: tailnum <chr>, n <int>
weather %>%
count(year, month, day, hour, origin) %>%
filter(n > 1)
#> Source: local data frame [0 x 6]
#> Groups: year, month, day, hour [0]
#>
#> # ... with 6 variables: year <dbl>, month <dbl>, day <int>,
#> # hour <int>, origin <chr>, n <int>
合并连接可以将两个表格中的变量组合起来,它先通过两个表格的键匹配观测,然后将一个表格中的变量复制到另一个表格中。下面借助图形来帮助理解连接的原理:
有颜色的列表示作为“键”的变量:它们用于在表间匹配行。灰色列表示“值”列,是与键对应的值。
只要两个观测的键是相等的,内连接就可以匹配他们,没有匹配的行不会包含在结果中。
外连接保留至少存在于一个表中的观测。它有3种连接类型,这些连接会向每个表中添加额外的“虚拟”观测,这个观测的值用NA来填充。
连接方式 | 作用 |
---|---|
左连接 | 保留x中的所有观测 |
右连接 | 保留y中的所有观测 |
全连接 | 保留x和y中的所有观测 |
图形表示如下:
筛选连接匹配观测的方式与合并连接相同,但前者影响的是观测,而不是变量。筛选连接有两种类型:
集合操作都是作用于整行的,比较的是每个变量的值。集合操作需要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
)
4种可能的集合操作为:
intersect(df1, df2)
#> # A tibble: 1 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 1
# 注意,我们得到了3行,而不是4行
union(df1, df2)
#> # A tibble: 3 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 2
#> 2 2 1
#> 3 1 1
setdiff(df1, df2)
#> # A tibble: 1 × 2
#> x y
#> <dbl> <dbl>
#> 1 2 1
setdiff(df2, df1)
#> # A tibble: 1 × 2
#> x y
#> <dbl> <dbl>
#> 1 1 2