2017-10-01 2 views
0

J'ai deux dataframes que je suis en train de fusionner:Fusion de deux dataframes sur plusieurs colonnes

set.seed(123) 
df1 <- data.frame(ID=sample(letters[1:6],10,replace=TRUE)) 
df2 <- data.frame(
    ID1 = letters[1:2], 
    ID2 = letters[3:4], 
    ID3 = letters[5:6], 
    V1 = c(23.32,21.24), 
    V2 = c(45.32,47.21) 
) 

fusion Post, je veux que mon df1 pour contenir les colonnes V1 et V2 avec ID. J'ai essayé d'utiliser merge, left_join et inner_join (à partir de dplyr) mais ne peux pas comprendre comment utiliser l'argument by. La colonne ID de df1 peut exister dans l'une quelconque des trois colonnes (ID1, ID2 et ID3) de df2. Comment puis-je atteindre cet objectif?

Répondre

1

Vous avez à remodeler au format long, puis rejoindre:

library(dplyr) 
library(tidyr) 

df2 %>% 
    gather(IDnr, ID, 1:3) %>% 
    left_join(df1, ., by = 'ID') 

# alternative: 
df1 %>% 
    left_join(., df2 %>% gather(IDnr, ID, 1:3), by = 'ID') 

Le résultat:

ID V1 V2 IDnr 
1 d 21.24 47.21 ID2 
2 e 23.32 45.32 ID3 
3 f 21.24 47.21 ID3 
4 d 21.24 47.21 ID2 
5 f 21.24 47.21 ID3 
6 c 23.32 45.32 ID2 
7 a 23.32 45.32 ID1 
8 e 23.32 45.32 ID3 
9 a 23.32 45.32 ID1 
10 d 21.24 47.21 ID2 
+0

parfait, merci! – Dhiraj

0

L'argument by est utilisé pour spécifier les colonnes d'identité que vous souhaitez joindre à supposer qu'ils sont nommés différemment pour les tables de droite & (si c'est le même nom, il choisira automatiquement).

Cependant, j'ai un moyen de simplifier ce que vous voulez faire. Tout d'abord, pourquoi ne pas remodeler df2 pour avoir seulement 1 colonne ID unique (supposer que l'ID est unique dans les 3 colonnes). Vous pouvez le faire en créant 3 dfs séparés et ensuite union ensemble en utilisant bind_rows.

Maintenant qu'il est remodelé, vous pouvez effectuer une jointure à droite. df1 est sur le côté droit de la jointure et tous les enregistrements dans df1 resteront s'il y a ou non une correspondance avec df2 (sinon V1 et V2 seront NULL, c'est-à-dire NA). Avec les exemples de données fournis par df1, les résultats seraient inattendus car chaque ID est répété et non unique (j'ai donc redéfini df1 pour avoir des ID uniques uniquement). Si les ID ne sont pas uniques, vous pouvez regrouper les résultats par ID et effectuer une agrégation avant de procéder à la jointure.

set.seed(123) 
#df1 <- data.frame(ID=sample(letters[1:6],10,replace=TRUE)) #This one has repeated IDs 
df1 <- data.frame(ID=letters[1:6]) 
df2 <- data.frame(
    ID1 = letters[1:2], 
    ID2 = letters[3:4], 
    ID3 = letters[5:6], 
    V1 = c(23.32,21.24), 
    V2 = c(45.32,47.21) 
) 

library(dplyr) 
#> Warning: package 'dplyr' was built under R version 3.4.2 
#> 
#> Attaching package: 'dplyr' 
#> The following objects are masked from 'package:stats': 
#> 
#>  filter, lag 
#> The following objects are masked from 'package:base': 
#> 
#>  intersect, setdiff, setequal, union 
df <- bind_rows(df2 %>% select(ID=ID1, V1, V2), 
       df2 %>% select(ID=ID2, V1, V2), 
       df2 %>% select(ID=ID3, V1, V2)) %>% 
     right_join(df1) 
#> Warning in bind_rows_(x, .id): Unequal factor levels: coercing to character 
#> Warning in bind_rows_(x, .id): binding character and factor vector, 
#> coercing into character vector 

#> Warning in bind_rows_(x, .id): binding character and factor vector, 
#> coercing into character vector 

#> Warning in bind_rows_(x, .id): binding character and factor vector, 
#> coercing into character vector 
#> Joining, by = "ID" 
#> Warning: Column `ID` joining character vector and factor, coercing into 
#> character vector 
df 
#> ID V1 V2 
#> 1 a 23.32 45.32 
#> 2 b 21.24 47.21 
#> 3 c 23.32 45.32 
#> 4 d 21.24 47.21 
#> 5 e 23.32 45.32 
#> 6 f 21.24 47.21