首页 > 解决方案 > 将数据框中的每一行与另一个数据框中的多行进行比较并获得结果

问题描述

我有 2 个数据集 df1 和 df2。

df1
c1  match   c3      c4
AA1 AB      cat     dog
AA1 CD      dfs     abd
AA1 EF      js      hn
AA1 GH      bsk     jtd
AA2 AB      cat     mouse
AA2 CD      adb     mop
AA2 EF      powas   qwert
AA2 GH      sms     mms
AA3 AB      i       j
AA3 CD      fgh     ejk
AA3 EF      mib     loi
AA3 GH      revit   roger

df2
match   d2      result
AB      cat     friendly
AB      mouse   enemy
CD      dfs     r1
CD      adb     r1
CD      fgh     r2
CD      ejk     r3
EF      mib     some_result
GH      sms     sent
GH      mms     sent
IJ      xxx     yyy
KL      crt     zzz
KL      rrr     qqq

我想通过“match”列匹配 df1 和 df2,并在 df1 中添加 2 个新列“result_c1”和“result_c2”。result_c1 从 df2 中得到对应的结果,首先匹配匹配列,然后将 df1 中的 c3 匹配到 df2 中的 d2。result_c2 从 df2 中得到对应的结果,首先匹配 match 列,然后将 df1 中的 c4 匹配到 df2 中的 d2。如果没有匹配,则返回“no_match”。有没有一种有效的方法来做到这一点?

result
c1  match   c3      c4      result_c1   result_c2   
AA1 AB      cat     dog     friendly    no_match    
AA1 CD      dfs     adb     r1          r1          
AA1 EF      js      hn      no_match    no_match    
AA1 GH      bsk     jtd     no_match    no_match    
AA2 AB      cat     mouse   friendly    enemy       
AA2 CD      adb     mop     r1          no_match    
AA2 EF      powas   qwert   no_match    no_match    
AA2 GH      sms     mms     sent        sent        
AA3 AB      i       j       no_match    no_match    
AA3 CD      fgh     ejk     r2          r3          
AA3 EF      mib     loi     some_result no_match    
AA3 GH      revit   roger   no_match    no_match    

数据附在下面:

df1 <- data.frame(list(c1 = c("AA1", "AA1", "AA1", "AA1", "AA2", "AA2", "AA2", "AA2",
                      "AA3", "AA3", "AA3", "AA3"), match = c("AB", "CD", "EF", "GH", 
                                                             "AB", "CD", "EF", "GH", 
                                                             "AB", "CD", "EF", "GH"),
                      c3 = c("cat", "dfs", "js", "bsk", "cat", "adb", "powas", "sms", "i",
                      "fgh", "mib", "revit"), c4 = c("dog", "abd", "hn", "jtd", "mouse",
                                                     "mop", "qwert", "mms", "j", "ejk", "loi", "roger")))

df2 <- data.frame(list(match = c("AB", "AB", "CD", "CD", "CD", "CD", "EF", "GH", "GH", "IJ", "KL", "KL"), 
                       d2 = c("cat", "mouse", "dfs", "adb", "fgh", "ejk", "mib", "sms", "mms", "xxx", "crt", "rrr"),
                       result = c("friendly", "enemy", "r1", "r1", "r2", "r3", "some_result", "sent", "sent", "yyy", "zzz", "qqq")))

谢谢你。

标签: rdataframe

解决方案


dplyr使用自定义函数的一种方法

apply_fun <- function(x, y, r) {
   inds <- x %in% y
   if (any(inds)) r[match(x[which.max(inds)], y)] else "no_match"
}

library(dplyr)
df1 %>%
  left_join(df2, by = "match") %>%
  mutate_all(as.character) %>%
  group_by(c1, match) %>%
  summarise(result_c1 = apply_fun(c3, d2, result), 
            result_c2 = apply_fun(c4, d2, result))

#   c1    match result_c1   result_c2
#   <chr> <chr> <chr>       <chr>    
# 1 AA1   AB    friendly    no_match 
# 2 AA1   CD    r1          no_match 
# 3 AA1   EF    no_match    no_match 
# 4 AA1   GH    no_match    no_match 
# 5 AA2   AB    friendly    enemy    
# 6 AA2   CD    r1          no_match 
# 7 AA2   EF    no_match    no_match 
# 8 AA2   GH    sent        sent     
# 9 AA3   AB    no_match    no_match 
#10 AA3   CD    r2          r3       
#11 AA3   EF    some_result no_match 
#12 AA3   GH    no_match    no_match 

推荐阅读