> 合并两个数据集 Radiant 中提供了六种来自 Hadley Wickham 等人开发的dplyr包的 “连接(join)”(或 “合并(merge)”)选项。 以下示例改编自 Jenny Bryan 的《dplyr 连接函数速查表》,聚焦三个小型数据集(superheroes、publishers和avengers),以说明 R 和 Radiant 中不同的连接类型及其他数据集合并方式。这些数据也可通过以下链接获取 csv 格式文件: * superheroes.csv * publishers.csv * avengers.csv
Superheroes
name alignment gender publisher
Magneto bad male Marvel
Storm good female Marvel
Mystique bad female Marvel
Batman good male DC
Joker bad male DC
Catwoman bad female DC
Hellboy good male Dark Horse Comics
Publishers
publisher yr_founded
DC 1934
Marvel 1939
Image 1992
在下方`数据>合并` 标签页的截图中,我们可以看到两个数据集。这两个表格共享 “出版商(publisher)” 变量,该变量会被自动选为连接键。`合并方式` 下拉菜单中提供了不同的连接选项。你也可以在 `合并后的数据集名称` 文本输入框中指定合并后数据集的名称。


### 内连接(超级英雄 × 出版商) 若 x = 超级英雄数据集,y = 出版商数据集: > 内连接返回 x 中与 y 有匹配值的所有行,以及 x 和 y 的所有列。若 x 和 y 之间存在多个匹配,所有匹配组合都会被返回。
name alignment gender publisher yr_founded
Magneto bad male Marvel 1939
Storm good female Marvel 1939
Mystique bad female Marvel 1939
Batman good male DC 1934
Joker bad male DC 1934
Catwoman bad female DC 1934
在上述表格中,我们丢失了 “地狱男爵(Hellboy)”,因为尽管这个英雄出现在`superheroes`数据集中,但其出版商(黑马漫画)未出现在`publishers`数据集中。连接结果包含`superheroes`的所有变量,以及来自`publishers`的 “成立年份(yr_founded)” 变量。我们可以用下方的维恩图可视化内连接:

R(Radiant)命令如下: ```r # Radiant combine_data(superheroes, publishers, by = "publisher", type = "inner_join") # R inner_join(superheroes, publishers, by = "publisher") ```
### 左连接(超级英雄 × 出版商) > 左连接返回 x 的所有行,以及 x 和 y 的所有列。若 x 和 y 之间存在多个匹配,所有匹配组合都会被返回。
name alignment gender publisher yr_founded
Magneto bad male Marvel 1939
Storm good female Marvel 1939
Mystique bad female Marvel 1939
Batman good male DC 1934
Joker bad male DC 1934
Catwoman bad female DC 1934
Hellboy good male Dark Horse Comics NA
连接结果包含`superheroes`的所有数据,以及来自`publishers`的 “成立年份(yr_founded)” 变量。“地狱男爵” 的出版商未出现在`publishers`中,因此其 “成立年份” 为`NA`。我们可以用下方的维恩图可视化左连接:

R(Radiant)命令如下: ```r # Radiant combine_data(superheroes, publishers, by = "publisher", type = "left_join") # R left_join(superheroes, publishers, by = "publisher") ```
### 右连接(超级英雄 × 出版商) > 右连接返回 y 的所有行,以及 y 和 x 的所有列。若 y 和 x 之间存在多个匹配,所有匹配组合都会被返回。
name alignment gender publisher yr_founded
Magneto bad male Marvel 1939
Storm good female Marvel 1939
Mystique bad female Marvel 1939
Batman good male DC 1934
Joker bad male DC 1934
Catwoman bad female DC 1934
NA NA NA Image 1992
连接结果包含`publishers`的所有行和列,以及`superheroes`的所有变量。我们丢失了 “地狱男爵”,因为其出版商未出现在`publishers`中。“图像漫画(Image)” 被保留在表格中,但来自`superheroes`的 “姓名(name)”“阵营(alignment)” 和 “性别(gender)” 变量为`NA`。请注意,连接可能会改变行和变量的顺序,因此在分析中不应依赖这些顺序。我们可以用下方的维恩图可视化右连接:

R(Radiant)命令如下: ```r # Radiant combine_data(superheroes, publishers, by = "publisher", type = "right_join") # R right_join(superheroes, publishers, by = "publisher") ```
### 全连接(超级英雄 × 出版商) > 全连接合并两个数据集,保留出现在任一数据集中的行和列。
name alignment gender publisher yr_founded
Magneto bad male Marvel 1939
Storm good female Marvel 1939
Mystique bad female Marvel 1939
Batman good male DC 1934
Joker bad male DC 1934
Catwoman bad female DC 1934
Hellboy good male Dark Horse Comics NA
NA NA NA Image 1992
在这个表格中,我们保留了 “地狱男爵”(即使 “黑马漫画” 不在`publishers`中)和 “图像漫画”(即使该出版商未在`superheroes`中列出),并获取了两个数据集的变量。没有匹配项的观测在来自另一个数据集的变量中被赋值为 NA。我们可以用下方的维恩图可视化全连接:

R(Radiant)命令如下: ```r # Radiant combine_data(superheroes, publishers, by = "publisher", type = "full_join") # R full_join(superheroes, publishers, by = "publisher") ``` ### 半连接(超级英雄 × 出版商) > 半连接仅保留 x 中的列。内连接会为 x 中每个与 y 匹配的行返回一行,而半连接绝不会复制 x 中的行。
name alignment gender publisher
Magneto bad male Marvel
Storm good female Marvel
Mystique bad female Marvel
Batman good male DC
Joker bad male DC
Catwoman bad female DC
我们得到了与`内连接`类似的表格,但仅包含`superheroes`中的变量。R(Radiant)命令如下: ```r # Radiant combine_data(superheroes, publishers, by = "publisher", type = "semi_join") # R semi_join(superheroes, publishers, by = "publisher") ```
### 反连接(超级英雄 × 出版商) > 反连接返回 x 中与 y 无匹配值的所有行,仅保留 x 中的列。
name alignment gender publisher
Hellboy good male Dark Horse Comics
现在我们**只**得到了 `地狱男爵`—— 唯一未在`publishers`中找到对应出版商的超级英雄,且未包含 “成立年份(yr_founded)” 变量。我们可以用下方的维恩图可视化反连接:


### 数据集顺序 请注意,所选数据集的顺序可能会影响连接结果。如果我们如下设置 `数据> 合并` 标签页,结果如下:


### 内连接(出版商 × 超级英雄)
publisher yr_founded name alignment gender
DC 1934 Batman good male
DC 1934 Joker bad male
DC 1934 Catwoman bad female
Marvel 1939 Magneto bad male
Marvel 1939 Storm good female
Marvel 1939 Mystique bad female
每个在`superheroes`中有匹配项的出版商都会多次出现,每个匹配项对应一行。除变量和行的顺序外,这与上方显示的内连接结果相同。
### 左连接和右连接(出版商 × 超级英雄) 除行和变量顺序外,`publishers`与`superheroes`的左连接等价于`superheroes`与`publishers`的右连接。同样,`publishers`与`superheroes`的右连接等价于`superheroes`与`publishers`的左连接。
### 全连接(出版商 × 超级英雄) 如你所料,除行和变量顺序外,`publishers`与`superheroes`的全连接等价于`superheroes`与`publishers`的全连接。
### 半连接(出版商 × 超级英雄)
publisher yr_founded
DC 1934
Marvel 1939
通过半连接,交换数据集顺序的影响更为明显。尽管每个出版商有多个匹配项,但仅显示一次。与之对比,内连接中 “若 x 和 y 之间存在多个匹配,所有匹配组合都会被返回”。表格中丢失了出版商 “图像漫画(Image)”,因为它不在`superheroes`中。
### 反连接(出版商 × 超级英雄)
publisher yr_founded
Image 1992
仅保留了出版商 “图像漫画”,因为 “漫威” 和 “DC” 都在`superheroes`中。我们只保留了`publishers`中的变量。
### 合并数据集的其他工具(复仇者 × 超级英雄) 当两个数据集具有相同的列(或行)时,还有其他方法可将它们合并为新数据集。我们已使用过`superheroes`数据集,现在尝试将其与`avengers`数据合并。这两个数据集的行数和列数相同,且列名相同。 在下方 “数据> 合并” 标签页的截图中,我们可以看到这两个数据集。此处无需选择变量来合并数据集,`选择变量` 中的任何变量在下方命令中都会被忽略。同样,你可以在 `合并后的数据集` 文本输入框中指定合并后数据集的名称。


### 行绑定
name alignment gender publisher
Thor good male Marvel
Iron Man good male Marvel
Hulk good male Marvel
Hawkeye good male Marvel
Black Widow good female Marvel
Captain America good male Marvel
Magneto bad male Marvel
Magneto bad male Marvel
Storm good female Marvel
Mystique bad female Marvel
Batman good male DC
Joker bad male DC
Catwoman bad female DC
Hellboy good male Dark Horse Comics
如果`avengers`数据集旨在扩展超级英雄列表,我们可以将两个数据集上下堆叠。新数据集有 14 行和 4 列。由于`avengers`数据集中的编码错误(万磁王并非复仇者),新合并的数据集中出现了重复行,这可能是我们不希望看到的。 R(Radiant)命令如下: ```r # Radiant combine_data(avengers, superheroes, type = "bind_rows") # R bind_rows(avengers, superheroes) ```
### 列绑定
name...1 alignment...2 gender...3 publisher...4 name...5 alignment...6 gender...7 publisher...8
Thor good male Marvel Magneto bad male Marvel
Iron Man good male Marvel Storm good female Marvel
Hulk good male Marvel Mystique bad female Marvel
Hawkeye good male Marvel Batman good male DC
Black Widow good female Marvel Joker bad male DC
Captain America good male Marvel Catwoman bad female DC
Magneto bad male Marvel Hellboy good male Dark Horse Comics
如果数据集为相同超级英雄包含不同列,我们可以将两个数据集并排合并。在 Radiant 中,若尝试绑定同名列,会看到错误消息,这是我们应始终避免的情况。若已知两个数据集的行 ID 顺序相同但列完全不同,此方法可能有用。
### 交集
name alignment gender publisher
Magneto bad male Marvel
检查两个具有相同列的数据集是否有重复行的好方法是从`合并方式` 下拉菜单中选择 `交集`。`avengers`和`superheroes`数据中确实有一行完全相同(即万磁王)。 R(Radiant)命令与上方所示相同,只需将`bind_rows`替换为`intersect`。
### 并集
name alignment gender publisher
Thor good male Marvel
Iron Man good male Marvel
Hulk good male Marvel
Hawkeye good male Marvel
Black Widow good female Marvel
Captain America good male Marvel
Magneto bad male Marvel
Storm good female Marvel
Mystique bad female Marvel
Batman good male DC
Joker bad male DC
Catwoman bad female DC
Hellboy good male Dark Horse Comics
`avengers`和`superheroes`的 `并集` 会合并数据集,但会省略重复行(即仅保留万磁王的一行)。这可能是我们此处想要的结果。 R(Radiant)命令与上方所示相同,只需将`bind_rows`替换为`union`。
### 差集
name alignment gender publisher
Thor good male Marvel
Iron Man good male Marvel
Hulk good male Marvel
Hawkeye good male Marvel
Black Widow good female Marvel
Captain America good male Marvel
最后,`差集` 会保留`avengers`中不在`superheroes`中的行。若交换输入(即从 `数据集` 下拉菜单中选择`superheroes`,从 `合并对象` 下拉菜单中选择`superheroes`),最终会得到`superheroes`中不在`avengers`中的所有行。两种情况下,万磁王的条目都会被省略。 R(Radiant)命令与上方所示相同,只需将`bind_rows`替换为`setdiff`。
### 报告 > Rmd 通过点击屏幕左下角的图标或按键盘上的`ALT-enter`,向*报告 > Rmd*添加代码以(重新)创建合并后的数据集。 更多相关讨论请参见《R for data science》中关于关系数据的章节点击查看Tidy Explain。 ### R 函数 有关`combine_data`函数的帮助,请参见*数据 > 合并*