Сопоставление двух фреймов данных с несколькими столбцами и добавление столбца после совпадения

#r #dataframe #merge #match

#r #фрейм данных #слияние #сопоставление

Вопрос:

У меня есть два фрейма данных:

 df1 <- data.frame(assoc = c(2, 3.4, 4.6, -2.3, -1, 0.48, -0.4), 
                    con = c("A","B","C","D","E","F","T"))
df2 <- data.frame(pos = c("-3", "-2", "-1", "0", "1", "2", "3"),
                  col1 = c("A", "B", "B", "T", "T", "D", "E"),
                  col2 = c("B", "T", "D", "A", "E", "C","F"))
view(df1)

con    assoc 
 A     2  
 B     3.4
 C     4.6
 D    -2.3  
 E    -1
 F     0.48
 T    -0.4
  

Я хотел бы создать функцию для сопоставления фреймов данных, чтобы присвоенные значения из df1 отображались в виде новых столбцов в df2. Желаемый результат будет выглядеть следующим образом:

     pos   col1  con1  col2    con2 
    -3     A      2     B      3.4
    -2     B      3.4   T     -0.4
    -1     B      3.4   D     -2.3
     0     T     -0.4   A      2
     1     T     -0.4   E     -1 
     2     D     -2.3   C      4.6
     3     E     -1     F      0.48
  

Я пытался использовать:

 res <- merge(df1, df2)
view(res)
  

К сожалению, это сработало только для одного примера. Когда я добавил новый столбец, похоже, это не сработало.

Любая помощь будет высоко оценена!

Комментарии:

1. Как df1 связать с df2 ? Я не вижу ни одного совпадающего столбца

Ответ №1:

Похоже, вы пытаетесь дважды соединить df1 с df2 с помощью разных переменных:

 library(tidyr)

df1 %>%
  left_join(df1, by = c(col1 = "con")) %>% 
  left_join(df1, by = c(col2 = "con"))

#>   pos col1 col2 assoc.x assoc.y
#> 1  -3    A    B     2.0    3.40
#> 2  -2    B    T     3.4   -0.40
#> 3  -1    B    D     3.4   -2.30
#> 4   0    T    A    -0.4    2.00
#> 5   1    T    E    -0.4   -1.00
#> 6   2    D    C    -2.3    4.60
#> 7   3    E    F    -1.0    0.48
  

Или двойное слияние:

 merge(merge(df1, df2, by.x = "con", by.y = "col1"), 
      df2, by.x = "con", by.y = "col2")
#>   con assoc pos.x col2 pos.y col1
#> 1   A   2.0    -3    B     0    T
#> 2   B   3.4    -2    T    -3    A
#> 3   B   3.4    -1    D    -3    A
#> 4   D  -2.3     2    C    -1    B
#> 5   E  -1.0     3    F     1    T
#> 6   T  -0.4     0    A    -2    B
#> 7   T  -0.4     1    E    -2    B
  

Ответ №2:

Вы можете использовать match для этого две колонки, т.е.

 sapply(df2[-1], function(i)df1$assoc[match(i, df1$con)])

     col1  col2
[1,]  2.0  3.40
[2,]  3.4 -0.40
[3,]  3.4 -2.30
[4,] -0.4  2.00
[5,] -0.4 -1.00
[6,] -2.3  4.60
[7,] -1.0  0.48
  

Ответ №3:

Вы имеете в виду merge вот так?

 Reduce(
  function(x, y) merge(x, y, by = names(df1)),
  lapply(
    grep("col", names(df2), value = TRUE),
    function(y) merge(df1, df2, by.x = "con", by.y = y)
  )
)
  

что позволяет вам объединяться, если у вас есть нечто большее, чем просто col1 и col2 внутри df2 , что дает вам

   assoc con pos.x col2 pos.y col1
1  -0.4   T     0    A    -2    B
2  -0.4   T     1    E    -2    B
3  -1.0   E     3    F     1    T
4  -2.3   D     2    C    -1    B
5   2.0   A    -3    B     0    T
6   3.4   B    -2    T    -3    A
7   3.4   B    -1    D    -3    A
  

Ответ №4:

Использование for цикла

 out <- df2
for(cn in c("col1", "col2")) out <- merge(out, df1, by.x = cn, by.y = 'con', all.x = TRUE)