Fusionner les lignes de deux data frames
Lorsqu’on analyse des données, il peut arriver qu’on ait besoin de fusionner les lignes de plusieurs data frames pour constituer un seul grand tableau de données. Dans d’autres situations, on a besoin de savoir si des lignes sont redondantes sur plusieurs data frames, et si c’est le cas de fusionner les données, mais sans ces répétitions. On peut encore avoir besoin de créer un nouveau jeu de données en ne conservant que les lignes qui sont communes à deux data frames. Ou au contraire en ne conservant que les lignes présentes dans l’ un des deux fichiers.
Toutes ces situations peuvent être gérées avec les fonctions de combinaisons de lignes du package dplyr
Ce sont ces fonctions que je vous propose d’explorer dans cet article.
Les data
Pour illustrer les différents cas de figure, je vais utiliser les jeux de données fish1 et fish2. Je les ai créés à partir du jeu de données des captures de poissons (tag00076) de la base de données d’Eurostats.
Le jeu de données fish1, contient les prises de poissons (en tonnes) réalisées en 2006 pour la Belgique, le Danemark, la Croatie, l’Estonie, la Grèce et la Finlande :
print(fish1)
## # A tibble: 6 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Danemark 2006-01-01 867803. 2006
## 3 Croatie 2006-01-01 37830. 2006
## 4 Estonie 2006-01-01 83940. 2006
## 5 Grèce 2006-01-01 96695. 2006
## 6 Finlande 2006-01-01 112933. 2006
Le fichier nommé « fish2« , contient les mêmes informations pour la Belgique, le Danemark, la Croatie, la Norvège, le Portugal et la Turquie :
print(fish2)
## # A tibble: 6 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Danemark 2006-01-01 867803. 2006
## 3 Croatie 2006-01-01 37830. 2006
## 4 Norvège 2006-01-01 2246169. 2006
## 5 Portugal 2006-01-01 229016. 2006
## 6 Turquie 2006-01-01 488966 2006
Remarque : Les jeux de données fish1 et fish2 sont au format tibble. Néanmoins, les fonctions présentées plus loin, sont également utilisables avec des données au format data.frame.
Tester si les 2 jeux de données sont identiques
Avant de fusionner deux jeux de données, il peut être intéressant de vérifier si ceux-ci sont identiques ou non. Ici, nous savons que ce n’est pas le cas, mais lorsque le nombre de lignes est important, la vérification visuelle n’est pas toujours évidente. Dans cette situation, la fonction setequal() peut être employée
setequal(fish1, fish2)
## [1] FALSE
La fonction renvoie FALSE, ce qui signifie que les deux jeux de données ne sont pas identiques.
Pour celles ou ceux qui se demanderaient si l’ordre des données est important, la réponse est NON !
Pour le vérifier, je crée un fichier fish3, copie de fish1, puis j’ordonne les lignes par valeur croissante des captures de poissons (variables values) :
fish3 <- fish1 %>%
arrange(values)
fish3
## # A tibble: 6 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Croatie 2006-01-01 37830. 2006
## 3 Estonie 2006-01-01 83940. 2006
## 4 Grèce 2006-01-01 96695. 2006
## 5 Finlande 2006-01-01 112933. 2006
## 6 Danemark 2006-01-01 867803. 2006
Dés lors, les jeux de données fish1 et fish3 comportent les mêmes données, mais dans un ordre différent.
Dans cette situation, la fonction setequal() renvoit bien TRUE, ce qui signifie que les fichiers sont identiques:
setequal(fish1, fish3)
## [1] TRUE
Fusion de l'ensemble des lignes
Une première façon de vouloir combiner deux jeux de données peut consister à simplement les empiler l’un sur l’autre. Pour cela, on peut utiliser la fonction bind_rows() :
fish_tot <- bind_rows(fish1, fish2)
print(fish_tot)
## # A tibble: 12 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Danemark 2006-01-01 867803. 2006
## 3 Croatie 2006-01-01 37830. 2006
## 4 Estonie 2006-01-01 83940. 2006
## 5 Grèce 2006-01-01 96695. 2006
## 6 Finlande 2006-01-01 112933. 2006
## 7 Belgique 2006-01-01 22519. 2006
## 8 Danemark 2006-01-01 867803. 2006
## 9 Croatie 2006-01-01 37830. 2006
## 10 Norvège 2006-01-01 2246169. 2006
## 11 Portugal 2006-01-01 229016. 2006
## 12 Turquie 2006-01-01 488966 2006
Le jeu de données final comporte 12 lignes, c’est à dire les 6 lignes du data frame (tableau) fish 1 et les 6 lignes du data frame fish2.
Fusion basée sur l'union (au sens mathématique)
Une autre façon de vouloir combiner deux jeux de données peut consister à les empiler, mais en retirant les lignes du deuxième jeu de données qui sont déjà présentes dans le premier. Pour cela, on utilise la fonction union() :
fish_union12 <- dplyr::union(fish1, fish2)
print(fish_union12)
## # A tibble: 9 x 4
## geo time values Year
##
## 1 Estonie 2006-01-01 83940. 2006
## 2 Finlande 2006-01-01 112933. 2006
## 3 Turquie 2006-01-01 488966 2006
## 4 Croatie 2006-01-01 37830. 2006
## 5 Norvège 2006-01-01 2246169. 2006
## 6 Grèce 2006-01-01 96695. 2006
## 7 Portugal 2006-01-01 229016. 2006
## 8 Belgique 2006-01-01 22519. 2006
## 9 Danemark 2006-01-01 867803. 2006
Cette fois, le jeu de données ne comporte que 9 lignes. Les lignes correspondant à la Belgique, le Danemark et la Croatie ne sont présentes qu’une seule fois, alors qu’elles étaient aussi présentes dans le deuxième data frame.
Fusion basée sur l'intersection (au sens mathématique)
Dans certaines situations, on peut vouloir, au contraire, créer un nouveau jeu de données qui contiendra uniquement les lignes qui sont à la fois présentes dans le premier et dans le deuxième data frame.
Dans un premier temps, on peut visualiser ces lignes qui sont communes aux deux jeux de données, en employant la fonction semi_join()
semi_join(fish1, fish2)
## # A tibble: 3 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Danemark 2006-01-01 867803. 2006
## 3 Croatie 2006-01-01 37830. 2006
La fonction nous permet bien de visualiser les lignes correspondant à la Belgique, le Danemark et la Croatie.
Pour créer ce nouveau data frame qui ne contiendra que les lignes qui sont à la fois présentes dans le premier et dans le deuxième jeu de données, on emploie la fonction intersect(), comme ceci:
fish_inter12<- dplyr::intersect(fish1, fish2)
print(fish_inter12)
## # A tibble: 3 x 4
## geo time values Year
##
## 1 Belgique 2006-01-01 22519. 2006
## 2 Danemark 2006-01-01 867803. 2006
## 3 Croatie 2006-01-01 37830. 2006
Fusion basée sur la différence
Enfin, un dernier cas de figure est celui dans lequel on souhaite créer un jeu de données en ne conservant que les lignes présentes dans le premier data frame et absentes dans le deuxième.
Comme précédemment, on peut, dans un premier temps visualiser ces lignes en employant la fonction anti_join().
Par exemple, si l’on souhaite visualiser les lignes présentes dans fish1 et absentes de fish2, on utilisera la code suivant :
anti_join(fish1, fish2)
## # A tibble: 3 x 4
## geo time values Year
##
## 1 Estonie 2006-01-01 83940. 2006
## 2 Grèce 2006-01-01 96695. 2006
## 3 Finlande 2006-01-01 112933. 2006
Si l’on souhaite, au contraire, visualiser les lignes présentes dans fish2 et absente de fish1, on inversera l’ordre des data frames en argument de la fonction anti_join() :
anti_join(fish2, fish1)
## # A tibble: 3 x 4
## geo time values Year
##
## 1 Norvège 2006-01-01 2246169. 2006
## 2 Portugal 2006-01-01 229016. 2006
## 3 Turquie 2006-01-01 488966 2006
Enfin, pour créer les jeux de données correspondant, on utilisera les commandes suivantes :
fish_diff12 <- setdiff(fish1,fish2)
fish_diff12
## # A tibble: 6 x 2
## geo values
##
## 1 Belgique 22519.
## 2 Danemark 867803.
## 3 Croatie 37830.
## 4 Estonie 83940.
## 5 Grèce 96695.
## 6 Finlande 112933.
Et l’inverse :
fish_diff21 <- setdiff(fish2,fish1)
fish_diff21
## # A tibble: 6 x 2
## geo values
##
## 1 Belgique 22519.
## 2 Danemark 867803.
## 3 Croatie 37830.
## 4 Norvège 2246169.
## 5 Portugal 229016.
## 6 Turquie 488966
J’espère que ce petit article vous permettra de fusionner les lignes de vos jeux de données de façon plus sereine et plus optimale. Dans un prochain article, je vous montrerai comment fusionner deux jeux de données, mais en terme de variables cette fois, autrement dit de colonnes).
Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee
Crédits photos : MickaelGaida
Merci Claire pour ce nouvel article. IL est vraiment très utile.
Merci pour cet article. J’utilise beaucoup les différents joins de dplyr, mais je ne connaissais pas la fonction setequal() dont j’aurais souvent eu besoin !
Dans les parties 5 et 6, vous différenciez « visualiser » (avec semi_join et anti_join) et « créer » (avec intersect et setdiff)
Ne peut on pas utiliser chaque fonction à la fois pour visualiser et créer ? Si oui, quelle différence dans les résultats obtenus ?
merci Claire pour ce beau travail et surtout de mettre à notre disposition les résumés de ton connaissance. merci bien