通过列中的至少一个合并ID合并两个R数据帧

问题描述 投票:1回答:1

我有一个正在苦苦挣扎的联接问题,因为我要用于单独数据帧的联接ID分布在三个可能的ID列中。如果至少有一个ID匹配,我希望能够加入。我知道_join和merge函数接受列名的向量,但是有条件地使这项工作可行吗?

例如,如果我有以下两个数据帧:

df_A <- data.frame(dta = c("FOO", "BAR", "GOO"),
                   id1 = c("abc", "", "bcd"),
                   id2 = c("", "", "xyz"),
                   id3 = c("def", "fgh", ""), stringsAsFactors = F)


df_B <- data.frame(dta = c("FUU", "PAR", "KOO"),
                   id1 = c("abc", "", ""),
                   id2 = c("", "xyz", "zzz"),
                   id3 = c("", "", ""), stringsAsFactors = F)


> df_A
 dta id1 id2 id3
1 FOO abc     def
2 BAR         fgh
3 GOO bcd xyz   

> df_B
  dta id1 id2 id3
1 FUU abc        
2 PAR     xyz    
3 KOO     zzz  

我希望最终得到这样的结果:

 dta.x dta.y id1  id2  id3  
1 FOO  FUU   abc  ""   def    [matched on id1]
2 BAR  ""    ""   ""   fgh      [unmatched]
3 GOO  PAR   bcd  xyz  ""    [matched on id2]
4 KOO  ""    ""   zzz  ""      [unmatched]

这样将保留不匹配的dta1和dta1变量,但是在有匹配项(上面的行1 + 3)的情况下,dta1和dta2都将加入新表中。我感觉_join,merge或match都不能按原样工作,并且我需要编写一个函数,但是我不确定从哪里开始。任何帮助或想法表示赞赏。谢谢

r
1个回答
0
投票

[基本上,您想要做的是通过相应的ID进行联接,您可以做的是将原始ID列转换为id_columnid_value,因为您不想与“”联接,我是否删除了它。

library(tidyverse)
df_A_long <- df_A %>%
    pivot_longer(
        cols = -dta,
        names_to = "id_column",
        values_to = "id_value"
    ) %>%
    dplyr::filter(id_value != "")


df_B_long <- df_B %>%
    pivot_longer(
        cols = -dta,
        names_to = "id_column",
        values_to = "id_value"
    ) %>%
    dplyr::filter(id_value != "")

我们总是使用id_columnid_value加入A和B。

> df_B_long
# A tibble: 3 x 3
  dta   id_column id_value
  <chr> <chr>     <chr>   
1 FUU   id1       abc     
2 PAR   id2       xyz     
3 KOO   id2       zzz 
df_joined <- df_A_long %>%
    full_join(df_B_long, by = c("id_column","id_value"),suffix = c("1","2")) %>%
    pivot_wider(
        id_cols = c(dta1,dta2),
        names_from = id_column,
        values_from = id_value
    ) %>%
    mutate(
        dta1_has_value = !is.na(dta1),
        dta1 = ifelse(dta1_has_value,dta1,dta2),
        dta2 = ifelse(!dta1_has_value & !is.na(dta2),NA,dta2)
    ) %>%
    select(-dta1_has_value) %>%
    group_by(dta1) %>%
    summarise_all(
        ~ifelse(all(is.na(.x)),"",.x[!is.na(.x)])
    ) %>%
    {
        .[sort(colnames(df_joined))]
    }
> df_joined
# A tibble: 4 x 5
  dta1  dta2  id1   id2   id3  
  <chr> <chr> <chr> <chr> <chr>
1 BAR   ""    ""    ""    fgh  
2 FOO   FUU   abc   ""    def  
3 GOO   PAR   bcd   xyz   ""   
4 KOO   ""    ""    zzz   ""   
© www.soinside.com 2019 - 2024. All rights reserved.