变异连接将列从 y
添加到 x
,根据键匹配观察结果。有四种变异连接:内部连接和三个外部连接。
用法
inner_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL
)
# S3 method for data.frame
inner_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL,
na_matches = c("na", "never"),
multiple = "all",
unmatched = "drop",
relationship = NULL
)
left_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL
)
# S3 method for data.frame
left_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL,
na_matches = c("na", "never"),
multiple = "all",
unmatched = "drop",
relationship = NULL
)
right_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL
)
# S3 method for data.frame
right_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL,
na_matches = c("na", "never"),
multiple = "all",
unmatched = "drop",
relationship = NULL
)
full_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL
)
# S3 method for data.frame
full_join(
x,
y,
by = NULL,
copy = FALSE,
suffix = c(".x", ".y"),
...,
keep = NULL,
na_matches = c("na", "never"),
multiple = "all",
relationship = NULL
)
参数
- x, y
-
一对数据帧、数据帧扩展(例如 tibble)或惰性数据帧(例如来自 dbplyr 或 dtplyr)。有关更多详细信息,请参阅下面的方法。
- by
-
使用
join_by()
创建的连接规范,或要连接的变量的字符向量。如果
NULL
(默认值),*_join()
将使用x
和y
之间的所有共同变量执行自然连接。一条消息列出了变量,以便您可以检查它们是否正确;通过显式提供by
来抑制该消息。要连接
x
和y
之间的不同变量,请使用join_by()
规范。例如,join_by(a == b)
将匹配x$a
到y$b
。要连接多个变量,请使用带有多个表达式的
join_by()
规范。例如,join_by(a == b, c == d)
将x$a
与y$b
匹配,将x$c
与y$d
匹配。如果x
和y
之间的列名称相同,您可以通过仅列出变量名称来缩短列名称,例如join_by(a, c)
。join_by()
还可用于执行不等式连接、滚动连接和重叠连接。有关这些类型的连接的详细信息,请参阅?join_by 中的文档。对于简单的等式连接,您也可以指定要连接的变量名称的字符向量。例如,
by = c("a", "b")
将x$a
连接到y$a
并将x$b
连接到y$b
。如果x
和y
之间的变量名称不同,请使用命名字符向量,例如by = c("x_a" = "y_a", "x_b" = "y_b")
。要执行交叉联接,生成
x
和y
的所有组合,请参阅cross_join()
。 - copy
-
如果
x
和y
不是来自同一个数据源,并且copy
是TRUE
,则y
将被复制到与x
相同的源中。这允许您跨 src 连接表,但这是一项潜在昂贵的操作,因此您必须选择它。 - suffix
-
如果
x
和y
中存在未连接的重复变量,这些后缀将添加到输出中以消除它们的歧义。应该是长度为 2 的字符向量。 - ...
-
传递给方法的其他参数。
- keep
-
来自
x
和y
的连接键是否应该保留在输出中?-
如果默认为
NULL
,则等式连接仅保留x
中的键,而不等式连接则保留两个输入中的键。 -
如果是
TRUE
,则保留两个输入的所有键。 -
如果
FALSE
,则仅保留x
中的 key 。对于右连接和全连接,与仅存在于y
中的行对应的键列中的数据将合并到x
中的键列中。在加入不平等条件时不能使用。
-
- na_matches
-
两个
NA
或两个NaN
值应该匹配吗? - multiple
-
处理
x
中与y
中多个匹配的行。对于x
的每一行:-
"all"
(默认值)返回y
中检测到的每个匹配项。这与 SQL 的行为相同。 -
"any"
返回在y
中检测到的一个匹配项,但不保证将返回哪一个匹配项。如果您只需要检测是否至少有一个匹配项,它通常比"first"
和"last"
更快。 -
"first"
返回在y
中检测到的第一个匹配项。 -
"last"
返回在y
中检测到的最后一个匹配项。
-
- unmatched
-
应如何处理会导致删除行的不匹配键?
-
"drop"
从结果中删除不匹配的键。 -
如果检测到不匹配的键,
"error"
会引发错误。
unmatched
旨在防止您在连接期间意外删除行。它仅检查输入中可能会删除行的不匹配键。-
对于左连接,它检查
y
。 -
对于右连接,它检查
x
。 -
对于内部联接,它检查
x
和y
。在这种情况下,unmatched
也可以是长度为 2 的字符向量,以独立指定x
和y
的行为。
-
- relationship
-
处理
x
和y
的键之间的预期关系。如果从下面的列表中选择的期望无效,则会抛出错误。-
默认情况下
NULL
不希望x
和y
之间存在任何关系。但是,对于相等连接,它将检查多对多关系(这通常是意外的),并在发生这种情况时发出警告,鼓励您仔细查看输入或通过指定"many-to-many"
来明确此关系。有关更多详细信息,请参阅多对多关系部分。
-
"one-to-one"
期望:-
x
中的每一行最多与y
中的 1 行匹配。 -
y
中的每一行最多与x
中的 1 行匹配。
-
-
"one-to-many"
期望:-
y
中的每一行最多与x
中的 1 行匹配。
-
-
"many-to-one"
期望:-
x
中的每一行最多与y
中的 1 行匹配。
-
-
"many-to-many"
不执行任何关系检查,但允许您明确了解此关系(如果您知道它存在)。
relationship
不处理零匹配的情况。为此,请参阅unmatched
。 -
值
与x
相同类型的对象(包括相同的组)。尽可能保留x
的行和列的顺序。输出具有以下属性:
-
行受连接类型影响。
-
inner_join()
返回匹配的x
行。 -
left_join()
返回所有x
行。 -
right_join()
返回匹配的x
行,后跟不匹配的y
行。 -
full_join()
返回所有x
行,后跟不匹配的y
行。
-
-
输出列包括
x
中的所有列以及y
中的所有非键列。如果keep = TRUE
,则还包括y
中的关键列。 -
如果
x
和y
中的非键列具有相同的名称,则添加suffix
来消除歧义。如果keep = TRUE
以及x
和y
中的关键列具有相同的名称,则也会添加suffix
来消除它们的歧义。 -
如果
keep = FALSE
,则by
中包含的输出列将被强制为其在x
和y
之间的通用类型。
多对多关系
默认情况下,dplyr 通过抛出警告来防止平等连接中的多对多关系。当以下两个条件都成立时,就会发生这种情况:
-
x
中的一行与y
中的多行匹配。 -
y
中的一行与x
中的多行匹配。
这通常令人惊讶,因为大多数联接涉及一对一、一对多或多对一的关系,并且通常是不正确指定联接的结果。多对多关系特别有问题,因为它们可能导致从连接返回的行数出现笛卡尔爆炸。
如果需要多对多关系,请通过显式设置 relationship = "many-to-many"
来消除此警告。
在生产代码中,最好预先将 relationship
设置为您期望 x
和 y
的键之间存在的任何关系,因为如果数据与您的期望不符,这会强制立即发生错误。
不等式连接本质上通常会产生多对多关系,因此默认情况下它们不会发出警告,但在指定不等式连接时仍应格外小心,因为它们也有能力返回大量行。
滚动联接也不会对多对多关系发出警告,但许多滚动联接遵循多对一关系,因此设置 relationship = "many-to-one"
来强制执行此操作通常很有用。
请注意,在 SQL 中,大多数数据库提供程序不允许您指定两个表之间的多对多关系,而是要求您创建第三个联结表来生成两个一对多关系。
也可以看看
其他连接:cross_join()
、filter-joins
、nest_join()
例子
band_members %>% inner_join(band_instruments)
#> Joining with `by = join_by(name)`
#> # A tibble: 2 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 John Beatles guitar
#> 2 Paul Beatles bass
band_members %>% left_join(band_instruments)
#> Joining with `by = join_by(name)`
#> # A tibble: 3 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 Mick Stones NA
#> 2 John Beatles guitar
#> 3 Paul Beatles bass
band_members %>% right_join(band_instruments)
#> Joining with `by = join_by(name)`
#> # A tibble: 3 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 John Beatles guitar
#> 2 Paul Beatles bass
#> 3 Keith NA guitar
band_members %>% full_join(band_instruments)
#> Joining with `by = join_by(name)`
#> # A tibble: 4 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 Mick Stones NA
#> 2 John Beatles guitar
#> 3 Paul Beatles bass
#> 4 Keith NA guitar
# To suppress the message about joining variables, supply `by`
band_members %>% inner_join(band_instruments, by = join_by(name))
#> # A tibble: 2 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 John Beatles guitar
#> 2 Paul Beatles bass
# This is good practice in production code
# Use an equality expression if the join variables have different names
band_members %>% full_join(band_instruments2, by = join_by(name == artist))
#> # A tibble: 4 × 3
#> name band plays
#> <chr> <chr> <chr>
#> 1 Mick Stones NA
#> 2 John Beatles guitar
#> 3 Paul Beatles bass
#> 4 Keith NA guitar
# By default, the join keys from `x` and `y` are coalesced in the output; use
# `keep = TRUE` to keep the join keys from both `x` and `y`
band_members %>%
full_join(band_instruments2, by = join_by(name == artist), keep = TRUE)
#> # A tibble: 4 × 4
#> name band artist plays
#> <chr> <chr> <chr> <chr>
#> 1 Mick Stones NA NA
#> 2 John Beatles John guitar
#> 3 Paul Beatles Paul bass
#> 4 NA NA Keith guitar
# If a row in `x` matches multiple rows in `y`, all the rows in `y` will be
# returned once for each matching row in `x`.
df1 <- tibble(x = 1:3)
df2 <- tibble(x = c(1, 1, 2), y = c("first", "second", "third"))
df1 %>% left_join(df2)
#> Joining with `by = join_by(x)`
#> # A tibble: 4 × 2
#> x y
#> <dbl> <chr>
#> 1 1 first
#> 2 1 second
#> 3 2 third
#> 4 3 NA
# If a row in `y` also matches multiple rows in `x`, this is known as a
# many-to-many relationship, which is typically a result of an improperly
# specified join or some kind of messy data. In this case, a warning is
# thrown by default:
df3 <- tibble(x = c(1, 1, 1, 3))
df3 %>% left_join(df2)
#> Joining with `by = join_by(x)`
#> Warning: Detected an unexpected many-to-many relationship between `x` and `y`.
#> ℹ Row 1 of `x` matches multiple rows in `y`.
#> ℹ Row 1 of `y` matches multiple rows in `x`.
#> ℹ If a many-to-many relationship is expected, set `relationship =
#> "many-to-many"` to silence this warning.
#> # A tibble: 7 × 2
#> x y
#> <dbl> <chr>
#> 1 1 first
#> 2 1 second
#> 3 1 first
#> 4 1 second
#> 5 1 first
#> 6 1 second
#> 7 3 NA
# In the rare case where a many-to-many relationship is expected, set
# `relationship = "many-to-many"` to silence this warning
df3 %>% left_join(df2, relationship = "many-to-many")
#> Joining with `by = join_by(x)`
#> # A tibble: 7 × 2
#> x y
#> <dbl> <chr>
#> 1 1 first
#> 2 1 second
#> 3 1 first
#> 4 1 second
#> 5 1 first
#> 6 1 second
#> 7 3 NA
# Use `join_by()` with a condition other than `==` to perform an inequality
# join. Here we match on every instance where `df1$x > df2$x`.
df1 %>% left_join(df2, join_by(x > x))
#> # A tibble: 6 × 3
#> x.x x.y y
#> <int> <dbl> <chr>
#> 1 1 NA NA
#> 2 2 1 first
#> 3 2 1 second
#> 4 3 1 first
#> 5 3 1 second
#> 6 3 2 third
# By default, NAs match other NAs so that there are two
# rows in the output of this join:
df1 <- data.frame(x = c(1, NA), y = 2)
df2 <- data.frame(x = c(1, NA), z = 3)
left_join(df1, df2)
#> Joining with `by = join_by(x)`
#> x y z
#> 1 1 2 3
#> 2 NA 2 3
# You can optionally request that NAs don't match, giving a
# a result that more closely resembles SQL joins
left_join(df1, df2, na_matches = "never")
#> Joining with `by = join_by(x)`
#> x y z
#> 1 1 2 3
#> 2 NA 2 NA
相关用法
- R dplyr mutate 创建、修改和删除列
- R dplyr mutate_all 改变多列
- R dplyr group_trim 修剪分组结构
- R dplyr slice 使用行的位置对行进行子集化
- R dplyr copy_to 将本地数据帧复制到远程src
- R dplyr sample_n 从表中采样 n 行
- R dplyr consecutive_id 为连续组合生成唯一标识符
- R dplyr row_number 整数排名函数
- R dplyr band_members 乐队成员
- R dplyr nth 从向量中提取第一个、最后一个或第 n 个值
- R dplyr coalesce 找到第一个非缺失元素
- R dplyr group_split 按组分割 DataFrame
- R dplyr order_by 用于排序窗口函数输出的辅助函数
- R dplyr context 有关“当前”组或变量的信息
- R dplyr percent_rank 比例排名函数
- R dplyr recode 重新编码值
- R dplyr starwars 星球大战人物
- R dplyr desc 降序
- R dplyr between 检测值落在指定范围内的位置
- R dplyr cumall 任何、全部和平均值的累积版本
- R dplyr group_map 对每个组应用一个函数
- R dplyr do 做任何事情
- R dplyr nest_join 嵌套连接
- R dplyr pull 提取单列
- R dplyr group_by_all 按选择的变量进行分组
注:本文由纯净天空筛选整理自Hadley Wickham等大神的英文原创作品 Mutating joins。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。