Lorsqu’on analyse des données, il peut arriver qu’on ait besoin de fusionner les lignes de plusieurs tableaux de données (data frames), pour constituer un seul grand tableau de données.
Mais, parfois, ce ne sont pas les lignes que l’on a besoin d’assembler, mais les colonnes. Et comme pour la fusion des lignes, cet assemblage des colonnes de deux jeux de données (appelé aussi jointures) peut être réalisé de différentes façons.
Par exemple, il peut s’agir d’une simple juxtaposition des colonnes (ce qui est rarement intéressant), ou bien il peut s’agir d’un appariement des colonnes, c’est à dire avec prise en compte d’une variable qui va permettre de relier (ou de joindre) les valeurs d’une colonne du premier jeu de données avec les valeurs correspondantes d’une colonne du second jeu de données.
Cette fois encore, le package dplyr propose plusieurs fonctions permettant de fusionner (ou joindre) deux tableaux de données par leurs colonnes (on parle de jointures) .
D’après la cheat sheet du package dplyr
Ce sont ces fonctions que nous allons explorer dans cet article.
1. Premier exemple : une seule variable de jointure
1.1 Les data
Considérons un premier jeu de données, nommé “fish” qui contient les quantités de poissons (en tonnes) péchés pour une année donnée, par la Belgique, le Danemark, la Croatie, l’Estonie, la Grèce, et la Finlande.
1 2 3 4 5 6 7 8 9 |
print(fish) ## geo Capture ## 1 Belgique 26860.00 ## 2 Danemark 670212.83 ## 3 Croatie 72865.34 ## 4 Estonie 72421.83 ## 5 Grèce NA ## 6 Finlande 164833.42 |
Considérons également, un second jeu de données, nommé “bio” qui, lui, contient les superficies de cultures agricoles biologiques déclarées par la Belgique, le Danemark et de la Croatie, mais aussi (alors que ce n’est pas le cas du jeu de données “fish”) de la Norvège, du Portugal et de la Turquie.
1 2 3 4 5 6 7 8 9 |
print(bio) ## geo SurfaceBio ## 1 Belgique 56055 ## 2 Danemark 161251 ## 3 Croatie 29172 ## 4 Norvège 44681 ## 5 Portugal 171743 ## 6 Turquie 388547 |
1.2 Juxtaposition des colonnes
Une première façon de vouloir joindre ces deux jeux de données peut simplement consister à les “coller” l’un à côté de l’autre. Pour cela, on peut utiliser la fonction bind_cols().
1 2 3 4 5 6 7 8 9 10 11 |
library(tidyverse) data1 <- bind_cols(fish, bio) print(data1) ## geo Capture geo1 SurfaceBio ## 1 Belgique 26860.00 Belgique 56055 ## 2 Danemark 670212.83 Danemark 161251 ## 3 Croatie 72865.34 Croatie 29172 ## 4 Estonie 72421.83 Norvège 44681 ## 5 Grèce NA Portugal 171743 ## 6 Finlande 164833.42 Turquie 388547 |
On peut voir ici que les 2 colonnes du data frame “fish” ont été juxtaposées aux 2 colonnes du data frame “bio”, et que la deuxième variable “geo” a été renommée “geo1”.
En regardant le data frame obtenu, on peut voir que si les données Capture et SurfaceBio des trois premières lignes concernent les mêmes pays, cela n’est plus le cas pour les trois lignes suivantes, puisque les données de pêche concernent l’Estonie, la Grèce et la Finlande et que les données de surfaces agricoles biologiques concernent la Norvège, le Portugal et la Turquie.
Ce n’est pas forcément ce que l’on souhaite !
1.3 Les jointures
1.3.1 Jointure à gauche
La jointure à gauche est réalisée avec la fonction left_join(). Cette fonction prend en argument les deux data frames à fusionner, ainsi que la variable de jointure (ou appariement).
1 |
left_join(df1, df2, by"var_jointure") |
Dans la jointure à gauche, le premier data frame cité dans la fonction (celui qui est donc à gauche), est le data frame de référence. Ce sont les colonnes du second data frame (celui qui est à droite dans la fonction) qui vont être ajoutées au data frame de référence. Mais seules les valeurs des lignes correspondant aux modalités de la variable de jointure présentes dans le data frame de référence seront ajoutées. C’est un peu complexe à formuler alors qu’en pratique, c’est plutôt simple. Voici un exemple pour mieux comprendre. On réalise une fusion à gauche entre les data frame ‘fish” et “bio”, en considérant le pays (variable “géo”), comme variable de jointure :
1 2 3 4 5 6 7 8 9 10 |
data2 <-left_join(fish, bio, by="geo") print(data2) ## geo Capture SurfaceBio ## 1 Belgique 26860.00 56055 ## 2 Danemark 670212.83 161251 ## 3 Croatie 72865.34 29172 ## 4 Estonie 72421.83 NA ## 5 Grèce NA NA ## 6 Finlande 164833.42 NA |
Le jeu de données “bio” ne contenant pas de valeur pour l’Estonie, la Grèce et la Finlande, des NA ont été ajoutées.
Remarque : si aucune variable de jointure n’est fournie à la fonction, l’appariement va être réalisé sur le plus grand nombre de variables commune (dans cet exemple, uniquement “geo”) .
1 2 3 4 5 6 7 8 9 10 |
data2_bis <-left_join(fish, bio) print(data2_bis) ## geo Capture SurfaceBio ## 1 Belgique 26860.00 56055 ## 2 Danemark 670212.83 161251 ## 3 Croatie 72865.34 29172 ## 4 Estonie 72421.83 NA ## 5 Grèce NA NA ## 6 Finlande 164833.42 NA |
1.3.2 Jointure à droite
La jointure à droite est réalisée avec la fonction right_join(). Son principe est identique, sauf qu’ici le data.frame de référence est celui entré en deuxième position (ici bio).
1 2 3 4 5 6 7 8 9 10 |
data3 <- right_join(fish, bio) print (data3) ## geo Capture SurfaceBio ## 1 Belgique 26860.00 56055 ## 2 Danemark 670212.83 161251 ## 3 Croatie 72865.34 29172 ## 4 Norvège NA 44681 ## 5 Portugal NA 171743 ## 6 Turquie NA 388547 |
Cette fois, ce sont les données de Surface biologiques qui sont complètes et les données de pêche de la Norvège, du Portugal et de la Turquie, qui ont été remplacées par des NA, car elles sont absentes du data frame “fish”.
1.3.3 Jointure restreinte
Une autre façon de fusionner les deux jeux de données, peut consister à ne considérer que les modalités communes de la variable de jointure (“geo”) présentes dans les deux data frames (ici la Belgique, le Danemark et la Croatie). Ce type de fusion est réalisé avec la fonction inner_join()
1 2 3 4 5 6 7 |
data4 <- inner_join(fish, bio, by="geo") print(data4) ## geo Capture SurfaceBio ## 1 Belgique 26860.00 56055 ## 2 Danemark 670212.83 161251 ## 3 Croatie 72865.34 29172 |
1.4.4 Jointure complète
Une dernière façon de fusionner les deux jeux de données, peut consister à considérer l’ensemble des modalités de la variable de jointure (“geo”), celles qui sont communes aux deux jeux de données (ici la Belgique, le Danemark et la Croatie) et celles qui sont uniquement présentes dans l’un des deux jeux de données. Ce type de fusion est réalisé avec la fonction full_join() :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
data5<- full_join(fish,bio) print(data5) ## geo Capture SurfaceBio ## 1 Belgique 26860.00 56055 ## 2 Danemark 670212.83 161251 ## 3 Croatie 72865.34 29172 ## 4 Estonie 72421.83 NA ## 5 Grèce NA NA ## 6 Finlande 164833.42 NA ## 7 Norvège NA 44681 ## 8 Portugal NA 171743 ## 9 Turquie NA 388547 |
Dans ce type de fusion, les deux data frames sont considérés sur le même plan, toutes les modalités de la variable d’ajustement, des deux data frames, sont considérées.
2. Second exemple : plusieurs variables de jointures
2.1 Les data
Considérons, à présent, le même fichier “fish”, mais avec en plus une variable “Year”, fixée à 2016 pour toutes les lignes. Ce jeu de donnée est renommé “fish_16”.
1 2 3 4 5 6 7 8 9 |
print(fish_16) ## geo Capture Year ## 1 Belgique 26860.00 2016 ## 2 Danemark 670212.83 2016 ## 3 Croatie 72865.34 2016 ## 4 Estonie 72421.83 2016 ## 5 Grèce NA 2016 ## 6 Finlande 164833.42 2016 |
Considérons aussi un nouveau jeu de données, concernant les surfaces agricoles biologiques. Ce nouveau jeu de données, nommé “bio_16_17” contient les superficies de cultures agricoles biologiques de la Belgique, du Danemark et de la Croatie pour l’année 2016, et celles de l’Estonie, de la Grèce et du Portugal, pour l’année 2017:
1 2 3 4 5 6 7 8 9 |
print(bio_16_17) ## geo SurfaceBio Year ## 1 Belgique 56055 2016 ## 2 Danemark 161251 2016 ## 3 Croatie 29172 2016 ## 4 Estonie 160837 2017 ## 5 Grèce 280733 2017 ## 6 Portugal 216180 2017 |
Examinons, comment se déroulent la juxtaposition et les jointures lorsque deux variables de jointure sont présentes :
2.2 Juxtaposition des colonnes
1 2 3 4 5 6 7 8 9 |
bind_cols(fish_16, bio_16_17) ## geo Capture Year geo1 SurfaceBio Year1 ## 1 Belgique 26860.00 2016 Belgique 56055 2016 ## 2 Danemark 670212.83 2016 Danemark 161251 2016 ## 3 Croatie 72865.34 2016 Croatie 29172 2016 ## 4 Estonie 72421.83 2016 Estonie 160837 2017 ## 5 Grèce NA 2016 Grèce 280733 2017 ## 6 Finlande 164833.42 2016 Portugal 216180 2017 |
Dans le cas de la juxtaposition, rien de nouveau, si ce n’est que cette fois, ce sont les 3 colonnes du data frame bio_16_17 qui ont été “collées” aux 3 colonnes du data frame bio_16_17.
2.3 Les jointures
2.3.1 Jointure à gauche
Comme mentionné précédemment, lorsque aucune variable de jointure n’est passée en argument, les fonctions x_join() utilisent, par défaut le maximum de variables de jointure (ici “geo” et “Year”).
1 2 3 4 5 6 7 8 9 10 |
mydata1 <- left_join(fish_16, bio_16_17) print(mydata1) ## geo Capture Year SurfaceBio ## 1 Belgique 26860.00 2016 56055 ## 2 Danemark 670212.83 2016 161251 ## 3 Croatie 72865.34 2016 29172 ## 4 Estonie 72421.83 2016 NA ## 5 Grèce NA 2016 NA ## 6 Finlande 164833.42 2016 NA |
Pour le vérifier, on peut passer “geo” et “Year” comme variables de jointure:
1 2 3 4 5 6 7 8 9 10 |
mydata1 <- left_join(fish_16, bio_16_17, by=c("geo", "Year")) print(mydata1) ## geo Capture Year SurfaceBio ## 1 Belgique 26860.00 2016 56055 ## 2 Danemark 670212.83 2016 161251 ## 3 Croatie 72865.34 2016 29172 ## 4 Estonie 72421.83 2016 NA ## 5 Grèce NA 2016 NA ## 6 Finlande 164833.42 2016 NA |
Les valeurs de Surface de cultures biologiques pour l’Estonie, la Grèce et la Finlande n’ont pas été renseignées, car elles sont relatives à l’année 2017. Elle ont donc été remplacées par des NA.
Remarque : puisque en l’absence de variable d’appariement, celle-ci se réalise, par défaut, sur l’ensemble des variables disponible, si l’on souhaite une jointure uniquement sur le pays, il est nécessaire de le préciser :
1 2 3 4 5 6 7 8 9 10 |
mydata1_bis <- left_join(fish_16, bio_16_17, by=c("geo")) print(mydata1_bis) ## geo Capture Year.x SurfaceBio Year.y ## 1 Belgique 26860.00 2016 56055 2016 ## 2 Danemark 670212.83 2016 161251 2016 ## 3 Croatie 72865.34 2016 29172 2016 ## 4 Estonie 72421.83 2016 160837 2017 ## 5 Grèce NA 2016 280733 2017 ## 6 Finlande 164833.42 2016 NA NA |
On voit que dans ce cas, la variable Year a été conservé pour les deux jeux de données, ce qui est plus prudent !
2.3.2 Jointure à droite
1 2 3 4 5 6 7 8 9 10 |
mydata3 <- right_join(fish_16, bio_16_17) print(mydata3) ## geo Capture Year SurfaceBio ## 1 Belgique 26860.00 2016 56055 ## 2 Danemark 670212.83 2016 161251 ## 3 Croatie 72865.34 2016 29172 ## 4 Estonie NA 2017 160837 ## 5 Grèce NA 2017 280733 ## 6 Portugal NA 2017 216180 |
Ici, se sont les données de pêche qui n’ont pas été complétées puisqu’elle concernent l’année 2016 alors qu’il s’agit de l’année 2017 dans le tableau qui sert de référence (bio_16_17).
2.3.3 Jointure restreinte
1 2 3 4 5 6 7 |
mydata4 <- inner_join(fish_16, bio_16_17) print(mydata4) ## geo Capture Year SurfaceBio ## 1 Belgique 26860.00 2016 56055 ## 2 Danemark 670212.83 2016 161251 ## 3 Croatie 72865.34 2016 29172 |
2.3.4 Jointure complète
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mydata5 <- full_join(fish_16, bio_16_17) print(mydata5) ## geo Capture Year SurfaceBio ## 1 Belgique 26860.00 2016 56055 ## 2 Danemark 670212.83 2016 161251 ## 3 Croatie 72865.34 2016 29172 ## 4 Estonie 72421.83 2016 NA ## 5 Grèce NA 2016 NA ## 6 Finlande 164833.42 2016 NA ## 7 Estonie NA 2017 160837 ## 8 Grèce NA 2017 280733 ## 9 Portugal NA 2017 216180 |
Voilà ! J’espère que l’exploration de ces fonctions left_join(), right_join(), inner_join() et full_join(), avec une et plusieurs variables de jointure, vous a permis de mieux comprendre ce processus de fusion de deux jeux de données par leurs colonnes.
Et si cet article vous a plu, comme d’habitude, partagez le !
Crédits photos : OpenClipart-vectors
Continuez votre lecture:
- Fusionner les lignes de deux data frames
- Nettoyer et valider les données avec R
- Initiation à la manipulation de données avec le package dplyr
- Gérer les dates et les heures avec le package lubridate
- 15Partages
15
Merci encore Claire, tu nous délivres ainsi des maux de tête que nous vivons lors du traitement de nos données. Je tiens vraiment à vous féliciter.