当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R dplyr mutate-joins 变异连接


变异连接将列从 y 添加到 x ,根据键匹配观察结果。有四种变异连接:内部连接和三个外部连接。

内部联接

inner_join() 仅保留 x 中在 y 中具有匹配键的观察结果。

内连接最重要的属性是任一输入中不匹配的行不会包含在结果中。这意味着通常内部联接在大多数分析中并不适用,因为它很容易丢失观察结果。

外连接

三个外连接保留至少出现在一个 DataFrame 中的观察结果:

  • left_join() 将所有观察结果保留在 x 中。

  • right_join() 将所有观察结果保留在 y 中。

  • full_join() 将所有观察结果保留在 xy 中。

用法

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() 将使用 xy 之间的所有共同变量执行自然连接。一条消息列出了变量,以便您可以检查它们是否正确;通过显式提供 by 来抑制该消息。

要连接 xy 之间的不同变量,请使用 join_by() 规范。例如, join_by(a == b) 将匹配 x$ay$b

要连接多个变量,请使用带有多个表达式的 join_by() 规范。例如, join_by(a == b, c == d)x$ay$b 匹配,将 x$cy$d 匹配。如果 xy 之间的列名称相同,您可以通过仅列出变量名称来缩短列名称,例如 join_by(a, c)

join_by() 还可用于执行不等式连接、滚动连接和重叠连接。有关这些类型的连接的详细信息,请参阅?join_by 中的文档。

对于简单的等式连接,您也可以指定要连接的变量名称的字符向量。例如, by = c("a", "b")x$a 连接到 y$a 并将 x$b 连接到 y$b 。如果 xy 之间的变量名称不同,请使用命名字符向量,例如 by = c("x_a" = "y_a", "x_b" = "y_b")

要执行交叉联接,生成 xy 的所有组合,请参阅 cross_join()

copy

如果 xy 不是来自同一个数据源,并且 copyTRUE ,则 y 将被复制到与 x 相同的源中。这允许您跨 src 连接表,但这是一项潜在昂贵的操作,因此您必须选择它。

suffix

如果 xy 中存在未连接的重复变量,这些后缀将添加到输出中以消除它们的歧义。应该是长度为 2 的字符向量。

...

传递给方法的其他参数。

keep

来自 xy 的连接键是否应该保留在输出中?

  • 如果默认为 NULL ,则等式连接仅保留 x 中的键,而不等式连接则保留两个输入中的键。

  • 如果是 TRUE ,则保留两个输入的所有键。

  • 如果 FALSE ,则仅保留 x 中的 key 。对于右连接和全连接,与仅存在于 y 中的行对应的键列中的数据将合并到 x 中的键列中。在加入不平等条件时不能使用。

na_matches

两个 NA 或两个 NaN 值应该匹配吗?

  • "na" (默认值)将两个 NA 或两个 NaN 值视为相等,例如 %in%match()merge()

  • "never" 将两个 NA 或两个 NaN 值视为不同的值,并且永远不会将它们匹配在一起或与任何其他值匹配。这类似于数据库源的联接和 base::merge(incomparables = NA)

multiple

处理 x 中与 y 中多个匹配的行。对于 x 的每一行:

  • "all" (默认值)返回 y 中检测到的每个匹配项。这与 SQL 的行为相同。

  • "any" 返回在 y 中检测到的一个匹配项,但不保证将返回哪一个匹配项。如果您只需要检测是否至少有一个匹配项,它通常比 "first""last" 更快。

  • "first" 返回在 y 中检测到的第一个匹配项。

  • "last" 返回在 y 中检测到的最后一个匹配项。

unmatched

应如何处理会导致删除行的不匹配键?

  • "drop" 从结果中删除不匹配的键。

  • 如果检测到不匹配的键,"error" 会引发错误。

unmatched 旨在防止您在连接期间意外删除行。它仅检查输入中可能会删除行的不匹配键。

  • 对于左连接,它检查 y

  • 对于右连接,它检查 x

  • 对于内部联接,它检查 xy 。在这种情况下,unmatched 也可以是长度为 2 的字符向量,以独立指定 xy 的行为。

relationship

处理 xy 的键之间的预期关系。如果从下面的列表中选择的期望无效,则会抛出错误。

  • 默认情况下 NULL 不希望 xy 之间存在任何关系。但是,对于相等连接,它将检查多对多关系(这通常是意外的),并在发生这种情况时发出警告,鼓励您仔细查看输入或通过指定 "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 中的关键列。

  • 如果xy 中的非键列具有相同的名称,则添加suffix 来消除歧义。如果 keep = TRUE 以及 xy 中的关键列具有相同的名称,则也会添加 suffix 来消除它们的歧义。

  • 如果 keep = FALSE ,则 by 中包含的输出列将被强制为其在 xy 之间的通用类型。

多对多关系

默认情况下,dplyr 通过抛出警告来防止平等连接中的多对多关系。当以下两个条件都成立时,就会发生这种情况:

  • x 中的一行与 y 中的多行匹配。

  • y 中的一行与 x 中的多行匹配。

这通常令人惊讶,因为大多数联接涉及一对一、一对多或多对一的关系,并且通常是不正确指定联接的结果。多对多关系特别有问题,因为它们可能导致从连接返回的行数出现笛卡尔爆炸。

如果需要多对多关系,请通过显式设置 relationship = "many-to-many" 来消除此警告。

在生产代码中,最好预先将 relationship 设置为您期望 xy 的键之间存在的任何关系,因为如果数据与您的期望不符,这会强制立即发生错误。

不等式连接本质上通常会产生多对多关系,因此默认情况下它们不会发出警告,但在指定不等式连接时仍应格外小心,因为它们也有能力返回大量行。

滚动联接也不会对多对多关系发出警告,但许多滚动联接遵循多对一关系,因此设置 relationship = "many-to-one" 来强制执行此操作通常很有用。

请注意,在 SQL 中,大多数数据库提供程序不允许您指定两个表之间的多对多关系,而是要求您创建第三个联结表来生成两个一对多关系。

方法

这些函数是泛型函数,这意味着包可以为其他类提供实现(方法)。有关额外参数和行为差异,请参阅各个方法的文档。

当前加载的包中可用的方法:

  • inner_join():dbplyr(tbl_lazy)、dplyr(data.frame)。

  • left_join():dbplyr(tbl_lazy)、dplyr(data.frame)。

  • right_join():dbplyr(tbl_lazy)、dplyr(data.frame)。

  • full_join():dbplyr(tbl_lazy)、dplyr(data.frame)。

也可以看看

其他连接:cross_join()filter-joinsnest_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/join.R

相关用法


注:本文由纯净天空筛选整理自Hadley Wickham等大神的英文原创作品 Mutating joins。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。