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

fusion de jeux de données
D'aprés la cheatsheet 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 lignesLes 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

6 réponses

  1. 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 !

  2. 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 ?

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *