r - 多列上的高效条件连接

r - Efficient conditional join on multiple columns

我有两个表,我想使用多列连接,使用 dplyr 连接函数完全可行。复杂的原因是我需要加入多个列,如果至少有一个列加入成功,则加入应该成功。为了证明我的情况,这里有一个可重现的例子:

df1 <- data.frame(
  A1 = c(1,2,3,4),
  B1 = c(4,5,6,7),
  C1 = c("a", "b", "c", "d")
)

df2 <- data.frame(
  A2 = c(8,"",3,4),
  B2 = c(9,5,"",7),
  C2 = c("aa", "bb", "cc", "dd")
)

我想在 A 列 B 上加入 df1df2,这意味着保留至少 df1$A = df2 的所有行$A 或 df1$B = df2$B(请注意我的真实数据集有 6 列我想用于连接)。简化示例的最终结果应为:

data.frame(
  A1 = c(2,3,4),
  A2 = c("",3,7),
  B1 = c(5,6,7),
  B2 = c(5,"", 7),
  C1 = c("b", "c", "d"),
  C2 = c("bb", "cc", "dd")
)

非常感谢有关如何有效完成此操作的任何建议,或者如果无法快速完成,那么也可以接受慢速解决方案

不太确定如何使用 dplyr 执行此操作,但 sqldf 可以帮助您:

library(sqldf)
sqldf("SELECT * 
       FROM df1
       JOIN df2 
       ON df1.A1 = df2.A2 
       OR df1.B1 = df2.B2")

您可以在此之后为更多列添加额外的 OR 语句。

这似乎不可能通过一次调用 dplyr 连接函数实现。

如果您想使用 dplyr 连接,这是我使用 purrr 映射函数创建的一个 hacky 解决方法,为条件连接中的每个条件执行单独的内部连接.然后将它们绑定在一起并删除重复的行。它可以通过附加到 key1key2 向量来泛化到更多列。

注意:首先我们需要修改示例数据,使要连接的列具有相同的类型。如果您尝试连接不兼容的列类型,dplyr 会引发错误,在本例中为整数和字符。

library(dplyr)
library(purrr)

df1 <- df1 %>%
  mutate(A1 = as.character(A1), B1 = as.character(B1))

key1 <- c('A1', 'B1')
key2 <- c('A2', 'B2')

map2_dfr(key1, key2, ~ inner_join(df1, df2, by = setNames(.y, .x), keep = TRUE)) %>%
  distinct()

结果:

  A1 B1 C1 A2 B2 C2
1  3  6  c  3    cc
2  4  7  d  4  7 dd
3  2  5  b     5 bb

一个简单的方法可以是:

library(dplyr)

df1 <- df1 %>%
  mutate(A1 = as.character(A1), B1 = as.character(B1))

df1 %>% 
  bind_cols(df2) %>% 
  filter(A1 == A2 | B1 == B2) %>% 
  relocate(sort(names(.)))

#>   A1 A2 B1 B2 C1 C2
#> 1  2     5  5  b bb
#> 2  3  3  6     c cc
#> 3  4  4  7  7  d dd