使用可变列连接表 - dplyr, r, join
Joining tables using variable columns - dplyr, r, join
问题: 我有 2 个表要加入。但是,我希望将第二个连接到第一个的列会有所不同,具体取决于对第二个数据框的成功解析以确定要连接的列和行。
请求: 我找到了解决问题的方法(见下文),但在我看来它的计算效率并不高。对于下面的可重现示例来说不是问题,但在涉及更大规模的问题时可能不太理想,即 ~200,000+ 行/观察。
想知道是否有人可以帮助识别更好的东西 - 最好利用 dplyr 的功能。
可重现示例:
# Equipment alias table
alias1 <- c('a1a1', 'a2a2', 'a3a3', 'a4a4', 'a5a5', 'a6a6')
alias2 <- c('bc001', 'bc002', 'bc003', 'bc004', 'bc005', 'bc006')
alias3 <- c('e1o1', 'e202', 'e303', 'e404', 'e505', 'e606')
df_alias <- data.frame(alias1, alias2, alias3)
# Attribute table
equip <- c('a1a1','bc006', 'e404')
att1 <- c('a', 'b', 'c')
att2 <- c('1', '2', '3')
df_att <- data.frame(equip, att1, att2)
期望的结果:
我希望实现以下目标....
# DESRIED OUTPUT - combining equipment alias table into attribute table based on string match between attibute_equip and any one of columns in equipment alias
equip <- c('a1a1','bc006', 'e404')
att1 <- c('a', 'b', 'c')
att2 <- c('1', '2', '3')
alias1 <- c('a1a1','a6a6', 'a4a4')
alias2 <- c('bc001','bc006', 'bc004')
alias3 <- c('e1o1','e606', 'e404')
df_att <- data.frame(equip, att1, att2, alias1, alias2, alias3)
当前解:
library(dplyr)
left_join(df_att, df_alias, by = character()) %>%
filter(equip == alias1 | equip == alias2 | equip == alias3)
有效但不完全优雅,因为存在大量重复,最终要应用过滤器来撤消重复。
一个选项是 filter
与 if_any
,然后将子集行与 df_att
绑定
library(dplyr)
df_att2 <- df_alias %>%
filter(if_any(everything(), ~ .x %in% df_att$equip)) %>%
arrange(na.omit(unlist(across(everything(), ~ match(df_att$equip, .x))))) %>%
bind_cols(df_att, .)
-检查 OP 的预期(将对象名称 'df_att' 更改为 'out' 以避免混淆)
> all.equal(df_att2, out)
[1] TRUE
我不知道它如何与 efficiency-wise 进行比较,但一个想法是旋转每个别名的副本,以便您可以 left_join
针对单个列而不是多个列。
library(tidyr)
library(dplyr)
df_alias %>%
mutate(across(everything(), ~., .names = "_{.col}")) %>%
pivot_longer(starts_with('_'), names_to = NULL, values_to = 'equip') %>%
left_join(df_att, .)
#> Joining, by = "equip"
#> equip att1 att2 alias1 alias2 alias3
#> 1 a1a1 a 1 a1a1 bc001 e1o1
#> 2 bc006 b 2 a6a6 bc006 e606
#> 3 e404 c 3 a4a4 bc004 e404
问题: 我有 2 个表要加入。但是,我希望将第二个连接到第一个的列会有所不同,具体取决于对第二个数据框的成功解析以确定要连接的列和行。
请求: 我找到了解决问题的方法(见下文),但在我看来它的计算效率并不高。对于下面的可重现示例来说不是问题,但在涉及更大规模的问题时可能不太理想,即 ~200,000+ 行/观察。
想知道是否有人可以帮助识别更好的东西 - 最好利用 dplyr 的功能。
可重现示例:
# Equipment alias table
alias1 <- c('a1a1', 'a2a2', 'a3a3', 'a4a4', 'a5a5', 'a6a6')
alias2 <- c('bc001', 'bc002', 'bc003', 'bc004', 'bc005', 'bc006')
alias3 <- c('e1o1', 'e202', 'e303', 'e404', 'e505', 'e606')
df_alias <- data.frame(alias1, alias2, alias3)
# Attribute table
equip <- c('a1a1','bc006', 'e404')
att1 <- c('a', 'b', 'c')
att2 <- c('1', '2', '3')
df_att <- data.frame(equip, att1, att2)
期望的结果:
我希望实现以下目标....
# DESRIED OUTPUT - combining equipment alias table into attribute table based on string match between attibute_equip and any one of columns in equipment alias
equip <- c('a1a1','bc006', 'e404')
att1 <- c('a', 'b', 'c')
att2 <- c('1', '2', '3')
alias1 <- c('a1a1','a6a6', 'a4a4')
alias2 <- c('bc001','bc006', 'bc004')
alias3 <- c('e1o1','e606', 'e404')
df_att <- data.frame(equip, att1, att2, alias1, alias2, alias3)
当前解:
library(dplyr)
left_join(df_att, df_alias, by = character()) %>%
filter(equip == alias1 | equip == alias2 | equip == alias3)
有效但不完全优雅,因为存在大量重复,最终要应用过滤器来撤消重复。
一个选项是 filter
与 if_any
,然后将子集行与 df_att
library(dplyr)
df_att2 <- df_alias %>%
filter(if_any(everything(), ~ .x %in% df_att$equip)) %>%
arrange(na.omit(unlist(across(everything(), ~ match(df_att$equip, .x))))) %>%
bind_cols(df_att, .)
-检查 OP 的预期(将对象名称 'df_att' 更改为 'out' 以避免混淆)
> all.equal(df_att2, out)
[1] TRUE
我不知道它如何与 efficiency-wise 进行比较,但一个想法是旋转每个别名的副本,以便您可以 left_join
针对单个列而不是多个列。
library(tidyr)
library(dplyr)
df_alias %>%
mutate(across(everything(), ~., .names = "_{.col}")) %>%
pivot_longer(starts_with('_'), names_to = NULL, values_to = 'equip') %>%
left_join(df_att, .)
#> Joining, by = "equip"
#> equip att1 att2 alias1 alias2 alias3
#> 1 a1a1 a 1 a1a1 bc001 e1o1
#> 2 bc006 b 2 a6a6 bc006 e606
#> 3 e404 c 3 a4a4 bc004 e404