{"id":832,"date":"2017-09-29T10:55:51","date_gmt":"2017-09-29T08:55:51","guid":{"rendered":"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=832"},"modified":"2017-09-29T10:57:42","modified_gmt":"2017-09-29T08:57:42","slug":"combinaisons-et-jointures-de-tables-avec-dplyr","status":"publish","type":"post","link":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/combinaisons-et-jointures-de-tables-avec-dplyr\/","title":{"rendered":"Combinaisons et jointures de tables, avec dplyr!"},"content":{"rendered":"<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/Lise_Vaudor_headband-1.png\" alt=\"\" \/><\/p>\n<p>Il y a quelques mois, je postais un <a href=\"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/dplyr\/\">billet concernant la manipulation de tableaux de donn\u00e9es avec <code>dplyr<\/code><\/a>, concernant plus particuli\u00e8rement <strong>la r\u00e9alisation de 5 op\u00e9rations de base sur des tableaux<\/strong> (s\u00e9lection de colonnes avec <code>select()<\/code>, filtrage de lignes avec <code>filter<\/code>, r\u00e9arrangement des lignes avec <code>arrange<\/code>, cr\u00e9ation ou modification de colonnes avec <code>mutate<\/code>, et synth\u00e9tisation statistique avec <code>summarise<\/code>).<\/p>\n<p>Aujourd&rsquo;hui, je vais aborder un type d&rsquo;op\u00e9ration diff\u00e9rent, \u00e0 savoir, les <strong>jointures de tableaux<\/strong> (i.e., grosso modo, comment \u00ab\u00a0coller\u00a0\u00bb deux tableaux ensemble pour en faire un seul).<\/p>\n<p>Pour ce faire, plut\u00f4t que de faire mes propres petits graphiques explicatifs (aussi beaux et roses soient-ils), je vais utiliser ceux fournis par RStudio et (plus particuli\u00e8rement) Garrett Grolemund dans leur <a href=\"https:\/\/github.com\/rstudio\/cheatsheets\/raw\/master\/data-transformation.pdf\">cheatsheet concernant la transformation de donn\u00e9es avec <code>dplyr<\/code><\/a>. Merci \u00e0 eux, donc, d&rsquo;abord pour avoir cr\u00e9\u00e9 cette \u00ab\u00a0antis\u00e8che\u00a0\u00bb tr\u00e8s utile, et ensuite pour m&rsquo;avoir autoris\u00e9e \u00e0 la d\u00e9couper en petits morceaux et la r\u00e9utiliser \u00e0 l&rsquo;envi ?&#8230;<\/p>\n<p>Avant toute chose, chargeons donc le package <code>dplyr<\/code>:<\/p>\n<pre><code>library(dplyr)\n<\/code><\/pre>\n<h2>Combinaison de deux tableaux<\/h2>\n<p>Dans une version tr\u00e8s tr\u00e8s simple, on peut simplement <strong>accoler<\/strong> ensemble deux tableaux, soit <strong>en colonnes<\/strong> (avec <code>bind_cols()<\/code>), soit <strong>en lignes<\/strong> (avec <code>bind_rows<\/code>).<\/p>\n<h1>Accolement de deux tableaux, en colonnes:<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/bind_cols.png\" alt=\"\" \/><\/p>\n<p>Dans ce premier cas, il est \u00e9videmment n\u00e9cessaire que les <strong>individus<\/strong> (et l&rsquo;<strong>ordre<\/strong> dans lequel ils apparaissent dans les deux tables) correspondent.<\/p>\n<p>Avec les deux tables x et y:<\/p>\n<pre><code>bind_cols(x, y)\n\n##   A B C A1 B1 D\n## 1 a t 1  a  t 3\n## 2 b u 2  b  u 2\n## 3 c v 3  d  w 1\n<\/code><\/pre>\n<p>Les noms de variables de la deuxi\u00e8me table, <code>y<\/code>, sont ici modifi\u00e9es pour \u00e9viter que plusieurs variables aient le m\u00eame nom.<\/p>\n<h1>Accolement de deux tableaux, en lignes:<\/h1>\n<p>Dans ce second cas, il est n\u00e9cessaire que les <strong>variables<\/strong> (et l&rsquo;<strong>ordre<\/strong> dans lequel elles apparaissent) correspondent.<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/bind_rows.png\" alt=\"\" \/><\/p>\n<pre><code>bind_rows(x,z)\n\n##   A B C\n## 1 a t 1\n## 2 b u 2\n## 3 c v 3\n## 4 c v 3\n## 5 d w 4\n<\/code><\/pre>\n<p>Si l&rsquo;on souhaite conserver une trace, dans le tableau final, de l&rsquo;origine des informations, on peut rajouter un <strong>identifiant<\/strong> de tableau de la mani\u00e8re suivante:<\/p>\n<pre><code>bind_rows(x,z,.id=\"myID\")\n\n##   myID A B C\n## 1    1 a t 1\n## 2    1 b u 2\n## 3    1 c v 3\n## 4    2 c v 3\n## 5    2 d w 4\n<\/code><\/pre>\n<p>Par d\u00e9faut, les identifiants seront simplement 1 et 2.<\/p>\n<p>Si vous souhaitez sp\u00e9cifier des identifiants diff\u00e9rents (par exemple, \u00ab\u00a0x\u00a0\u00bb, et \u00ab\u00a0z\u00a0\u00bb plut\u00f4t que 1 et 2), vous pouvez proc\u00e9der comme suit:<\/p>\n<pre><code>bind_rows(list(x=x,z=z), .id=\"myID\")\n\n##   myID A B C\n## 1    x a t 1\n## 2    x b u 2\n## 3    x c v 3\n## 4    z c v 3\n## 5    z d w 4\n<\/code><\/pre>\n<p>Il est \u00e9galement possible d&rsquo;accoler deux tableaux en lignes en utilisant l&rsquo;id\u00e9e d&rsquo;<strong>union<\/strong>, d&rsquo;<strong>intersection<\/strong> et de <strong>diff\u00e9rence<\/strong>&#8230;<\/p>\n<h1>\u00ab\u00a0Intersection\u00a0\u00bb de deux tableaux<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/intersect.png\" alt=\"\" \/><\/p>\n<pre><code>intersect(x,z)\n\n##   A B C\n## 1 c v 3\n<\/code><\/pre>\n<p>Dans le cas d&rsquo;une <strong>intersection<\/strong>, on ne <strong>retient que les individus communs aux deux tableaux<\/strong>.<\/p>\n<h1>\u00ab\u00a0Union\u00a0\u00bb de deux tableaux<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/union.png\" alt=\"\" \/><\/p>\n<pre><code>union(x,z)\n\n##   A B C\n## 1 c v 3\n## 2 a t 1\n## 3 b u 2\n## 4 d w 4\n<\/code><\/pre>\n<p>A la diff\u00e9rence d&rsquo;un simple appel \u00e0 <code>bind_rows()<\/code>, <code>union()<\/code> <strong>retire les lignes redondantes<\/strong>.<\/p>\n<h1>\u00ab\u00a0Diff\u00e9rence\u00a0\u00bb de deux tableaux<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/difference.png\" alt=\"\" \/><\/p>\n<pre><code>setdiff(x,z)\n\n##   A B C\n## 1 a t 1\n## 2 b u 2\n<\/code><\/pre>\n<p><code>setdiff()<\/code> ne <strong>retient que les lignes qui apparaissent dans le premier tableau et non dans le second<\/strong>.<\/p>\n<h2>Jointures<\/h2>\n<p>Dans une jointure, on \u00ab\u00a0colle ensemble\u00a0\u00bb des tableaux dont <strong>les lignes ne correspondent pas forc\u00e9ment<\/strong> (par exemple, \u00e0 une information situ\u00e9e en ligne 33 du premier tableau, correspond une information situ\u00e9e en ligne 158 du deuxi\u00e8me tableau).<\/p>\n<p>On peut distinguer <strong>plusieurs types de jointures<\/strong>.<\/p>\n<h1>Jointure \u00e0 gauche<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/left_join.png\" alt=\"\" \/><\/p>\n<p>Dans une <strong>jointure \u00e0 gauche<\/strong>, on <strong>adjoint aux informations de la table de gauche<\/strong> les informations issues de la table de droite:<\/p>\n<pre><code>left_join(x,y)\n\n## Joining, by = c(\"A\", \"B\")\n\n##   A B C  D\n## 1 a t 1  3\n## 2 b u 2  2\n## 3 c v 3 NA\n<\/code><\/pre>\n<p>Ainsi, c&rsquo;est <strong>le tableau de gauche qui d\u00e9finit les individus du tableau en sortie<\/strong> (quand bien-m\u00eame il n&rsquo;y a pas d&rsquo;information \u00e0 leur sujet dans le tableau de droite: remarquez ainsi la donn\u00e9e manquante dans la colonne <code>D<\/code> pour le 3i\u00e8me individu&#8230;)<\/p>\n<p>En mettant un peu de bazar dans les tables (autant que possible dans une table de 3 lignes ?),<\/p>\n<pre><code>x_mess=x[c(3,2,1),]\nprint(x_mess)\n\n##   A B C\n## 3 c v 3\n## 2 b u 2\n## 1 a t 1\n\ny_mess=y[c(1,3,2),]\nprint(y_mess)\n\n##   A B D\n## 1 a t 3\n## 3 d w 1\n## 2 b u 2\n<\/code><\/pre>\n<p>on voit mieux l&rsquo;int\u00e9r\u00eat de la jointure : voyez donc comme elle a bien sur faire le lien entre les deux tables malgr\u00e9 le bazar qu&rsquo;on y a mis:<\/p>\n<pre><code>left_join(x_mess,y_mess)\n\n## Joining, by = c(\"A\", \"B\")\n\n##   A B C  D\n## 1 c v 3 NA\n## 2 b u 2  2\n## 3 a t 1  3\n<\/code><\/pre>\n<p>Ici, on n&rsquo;a pas pr\u00e9cis\u00e9 pas <strong>quelle ligne de <code>x<\/code> allait avec quelle ligne de <code>y<\/code><\/strong>: de ce fait, la fonction a simplement suppos\u00e9 que les <strong>variables communes aux deux tableaux<\/strong> (ici <code>A<\/code> et <code>B<\/code>) permettaient d&rsquo;identifier les individus et de relier les informations des deux tables.<\/p>\n<p>Il est bien s\u00fbr possible (voire recommand\u00e9) de <strong>pr\u00e9ciser explicitement quelles sont les identifiants<\/strong> qui permettent de faire ce lien entre les deux tables, \u00e0 travers l&rsquo;argument <code>by<\/code>:<\/p>\n<pre><code>left_join(x,y, by=c(\"A\",\"B\"))\n\n##   A B C  D\n## 1 a t 1  3\n## 2 b u 2  2\n## 3 c v 3 NA\n<\/code><\/pre>\n<h1>Jointure \u00e0 droite<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/right_join.png\" alt=\"\" \/><\/p>\n<p>Dans une <strong>jointure \u00e0 droite<\/strong>, on <strong>adjoint aux informations de la table de droite<\/strong> les informations issues de la table de gauche.<\/p>\n<pre><code>right_join(x,y,by=c(\"A\",\"B\"))\n\n##   A B  C D\n## 1 a t  1 3\n## 2 b u  2 2\n## 3 d w NA 1\n<\/code><\/pre>\n<p>Ainsi, c&rsquo;est <strong>le tableau de droite qui d\u00e9finit les individus du tableau en sortie<\/strong> (quand bien-m\u00eame le tableau de gauche ne contiendrait pas d&rsquo;informations \u00e0 leur sujet: remarquez ainsi la donn\u00e9e manquante dans la colonne <code>C<\/code> pour le 3i\u00e8me individu&#8230; ).<\/p>\n<h1>Jointure interne<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/inner_join.png\" alt=\"\" \/><\/p>\n<p>Dans une <strong>jointure interne<\/strong>, ne sont conserv\u00e9s que <strong>les individus communs aux deux jeux de donn\u00e9es<\/strong>:<\/p>\n<pre><code>inner_join(x,y,by=c(\"A\",\"B\"))\n\n##   A B C D\n## 1 a t 1 3\n## 2 b u 2 2\n<\/code><\/pre>\n<h1>Jointure compl\u00e8te<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Jointures\/full_join.png\" alt=\"\" \/><\/p>\n<p>Dans le cas d&rsquo;une <strong>jointure compl\u00e8te<\/strong>, au contraire d&rsquo;une jointure interne, on <strong>conserve l&rsquo;ensemble des individus<\/strong> d\u00e9crits par l&rsquo;un ou l&rsquo;autre des jeux de donn\u00e9es&#8230;<\/p>\n<pre><code>full_join(x,y,by=c(\"A\",\"B\"))\n\n##   A B  C  D\n## 1 a t  1  3\n## 2 b u  2  2\n## 3 c v  3 NA\n## 4 d w NA  1\n<\/code><\/pre>\n<h1>Identifiants portant des noms diff\u00e9rents<\/h1>\n<p>Il arrive qu&rsquo;une variable identifiant les individus n&rsquo;ait <strong>pas le m\u00eame nom dans les deux tableaux<\/strong>&#8230; Dans ce cas on peut pr\u00e9ciser de faire correspondre \u00e0 une variable du premier tableau, une autre variable du deuxi\u00e8me tableau, de la mani\u00e8re suivante:<\/p>\n<pre><code># Fait correspondre x$C et y$D:\nfull_join(x,y,by=c(\"C\"=\"D\"))\n\n##   A.x B.x C A.y B.y\n## 1   a   t 1   d   w\n## 2   b   u 2   b   u\n## 3   c   v 3   a   t\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Il y a quelques mois, je postais un billet concernant la manipulation de tableaux de donn\u00e9es avec dplyr, concernant plus particuli\u00e8rement la r\u00e9alisation de 5 op\u00e9rations de base sur des tableaux (s\u00e9lection de colonnes avec select(), filtrage de lignes avec filter, r\u00e9arrangement des lignes avec arrange, cr\u00e9ation ou modification de colonnes avec mutate, et synth\u00e9tisation statistique avec summarise). Aujourd&rsquo;hui, je vais aborder un type d&rsquo;op\u00e9ration diff\u00e9rent, \u00e0 savoir, les jointures.. <a href=\"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/combinaisons-et-jointures-de-tables-avec-dplyr\/\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-832","post","type-post","status-publish","format-standard","hentry","category-tous-les-posts"],"_links":{"self":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/comments?post=832"}],"version-history":[{"count":12,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/832\/revisions"}],"predecessor-version":[{"id":844,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/832\/revisions\/844"}],"wp:attachment":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/media?parent=832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/categories?post=832"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/tags?post=832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}