Я хотел бы объединить 2 df, где в df1 содержится 2 столбца и df2 1 столбец, как в этом случае применить слияние функций?

Вот пример:

df1 <- data.frame(var1=letters[1:5],var2=letters[6:10])
df2 <- data.frame(var3=letters[1:10])

Ложная попытка:

merge(df1,df2,by.x=c("var1","var2"),by.y="var3",all.y=TRUE)

Как объединить эти два df, чтобы поиск совпадений использовал оба столбца df1 (var1 и var2) и работал с df2 (var3)?

Пожеланная выходная мощность:

    var1  var2   var3 
1     a    f       a
2     b    g       b
3     c    h       c
4     d    i       d
5     e    j       e
6     <NA> <NA>    f
7     <NA> <NA>    g
8     <NA> <NA>    h
9     <NA> <NA>    i 
10    <NA> <NA>    j

РЕДАКТИРОВАТЬ: улучшенные данные (надеюсь):

df1 <- data.frame(var1=c(letters[1:5],rep("x",5)),var2=c(letters[6:10],rep("x",5)))
df2 <- data.frame(var3=letters[1:10])

Пожеланная выходная мощность:

     var1  var2   var3 
 1     a    f       a
 2     b    g       b
 3     c    h       c
 4     d    i       d
 5     e    j       e
 6     x    x       f
 7     x    x       g
 8     x    x       h
 9     x    x       i 
10     x    x       j
5
Maximilian 23 Фев 2015 в 18:20

3 ответа

Лучший ответ

Вы можете использовать merge с аргументом by='row.names' и sort=F (как указал Мэтью Плурд), чтобы не позволить merge нарушить порядок:

> merge(df1, df2, by='row.names', sort=FALSE, all=TRUE)[c("var1", "var2", "var3")]
   var1 var2 var3
1     a    f    a
2     b    g    b
3     c    h    c
4     d    i    d
5     e    j    e
6  <NA> <NA>    i
7  <NA> <NA>    f
8  <NA> <NA>    g
9  <NA> <NA>    h
10 <NA> <NA>    j
5
user1981275 5 Мар 2015 в 01:55

Вам просто нужно изменить порядок df2 в соответствии с df1 и cbind их:

cbind(df1, df2[order(match(df2$var3, df1$var1)),, drop=FALSE])

Если df2 имеет более одного столбца, вам не нужно drop=FALSE.

#    var1 var2 var3
# 1     a    f    a
# 2     b    g    b
# 3     c    h    c
# 4     d    i    d
# 5     e    j    e
# 6     x    x    f
# 7     x    x    g
# 8     x    x    h
# 9     x    x    i
# 10    x    x    j

Придерживаясь этого подхода, для первого набора данных без xs вы можете использовать:

cbind(lapply(df1, `length<-`, nrow(df2)), df2[order(match(df2$var3, df1$var1)),, drop=FALSE])

#    var1 var2 var3
# 1     a    f    a
# 2     b    g    b
# 3     c    h    c
# 4     d    i    d
# 5     e    j    e
# 6  <NA> <NA>    f
# 7  <NA> <NA>    g
# 8  <NA> <NA>    h
# 9  <NA> <NA>    i
# 10 <NA> <NA>    j

Или более читабельным способом:

df1 <- lapply(df1, `length<-`, nrow(df2))
df2 <- df2[order(match(df2$var3, df1$var1)),, drop=FALSE]
cbind(df1, df2)
5
Matthew Plourde 23 Фев 2015 в 16:01

Вот возможное решение data.table для первого желаемого результата

library(data.table)
setkey(setDT(df2), var3)
df2[df1, `:=`(var1 = i.var1, var2 = i.var2)][]
#     var3 var1 var2
#  1:    a    a    f
#  2:    b    b    g
#  3:    c    c    h
#  4:    d    d    i
#  5:    e    e    j
#  6:    f   NA   NA
#  7:    g   NA   NA
#  8:    h   NA   NA
#  9:    i   NA   NA
# 10:    j   NA   NA
5
David Arenburg 23 Фев 2015 в 15:37