{"id":852,"date":"2017-11-15T14:27:26","date_gmt":"2017-11-15T13:27:26","guid":{"rendered":"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=852"},"modified":"2017-11-15T15:26:47","modified_gmt":"2017-11-15T14:26:47","slug":"manipulation-de-facteurs-avec-forcats","status":"publish","type":"post","link":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/manipulation-de-facteurs-avec-forcats\/","title":{"rendered":"Manipulation de facteurs avec forcats"},"content":{"rendered":"<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/Lise_Vaudor_headband-1.png\" alt=\"\" \/><\/p>\n<p>J&rsquo;ai r\u00e9cemment eu \u00e0 travailler avec des <strong>donn\u00e9es d&rsquo;enqu\u00eate<\/strong> (ce qui m&rsquo;arrive somme toute assez rarement) et notamment \u00e0 tenter de produire des <strong>tableaux<\/strong> et des <strong>figures<\/strong> rendant compte de ces donn\u00e9es, souvent <strong>cat\u00e9gorielles<\/strong>.<\/p>\n<p>J&rsquo;ai \u00e9t\u00e9 assez rapidement confront\u00e9e \u00e0 un probl\u00e8me qui peut sembler trivial de prime abord, mais qui n\u00e9anmoins n&rsquo;est pas si anecdotique que cela au regard du temps qu&rsquo;il peut faire perdre: la <strong>manipulation de factors<\/strong>, et notamment les <strong>changements d&rsquo;ordre et de noms de leurs niveaux<\/strong>.<\/p>\n<p>Ce <strong>changement de noms<\/strong> est souvent n\u00e9cessaire pour rendre les <strong>noms de niveaux explicites<\/strong> (i.e. transformation d&rsquo;un \u00ab\u00a0code\u00a0\u00bb, par exemple \u00ab\u00a0SiteTemAvt\u00a0\u00bb, en langage naturel, comme \u00ab\u00a0Site t\u00e9moin avant traitement\u00a0\u00bb). Quand au changement d&rsquo;ordre, il peut \u00eatre utile pour rendre compte d&rsquo;une <strong>ordination naturelle de niveaux<\/strong> (par exemple les niveaux \u00ab\u00a0Adolescent\u00a0\u00bb, \u00ab\u00a0Adulte\u00a0\u00bb, \u00ab\u00a0Enfant\u00a0\u00bb, \u00ab\u00a0Nourrisson\u00a0\u00bb d&rsquo;un factor \u00ab\u00a0Tranche d&rsquo;\u00e2ge\u00a0\u00bb devraient a priori s&rsquo;organiser dans l&rsquo;ordre \u00ab\u00a0Nourrisson\u00a0\u00bb,\u00a0\u00bbEnfant\u00a0\u00bb,\u00a0\u00bbAdolescent\u00a0\u00bb,\u00a0\u00bbAdulte\u00a0\u00bb).<\/p>\n<p>Or, ces op\u00e9rations peuvent \u00eatre assez p\u00e9nibles en n&rsquo;utilisant que les fonctions de R base. Je suis donc all\u00e9e faire un tour du c\u00f4t\u00e9 du <em>tidyverse<\/em> pour voir s&rsquo;il n&rsquo;existerait pas, par hasard, un package pour faire ce genre de choses&#8230; Et <em>bien s\u00fbr<\/em>, il y en a un. Il s&rsquo;agit du package <code>forcats<\/code> (nom de package qui confirme, une fois de plus, que le monde des d\u00e9veloppeurs R est un monde de crazy cat ladies et crazy cat buddies <em>ergo<\/em> je suis juste parfaitement adapt\u00e9e \u00e0 mon milieu).<\/p>\n<p>Je me suis donc empress\u00e9e d&rsquo;aller voir <a href=\"https:\/\/www.r-bloggers.com\/forcats-0-1-0-%F0%9F%90%88%F0%9F%90%88%F0%9F%90%88%F0%9F%90%88\/\">ce billet de blog<\/a> dont voici ci-apr\u00e8s ma r\u00e9-interpr\u00e9tation\/mise en images.<\/p>\n<p>Et pour un autre billet, toujours en fran\u00e7ais, et bien plus complet (et avec un vrai meme de chat -\u00e0 ne pas confondre avec la m\u00e9m\u00e8re \u00e0 chat-), c&rsquo;est <a href=\"https:\/\/thinkr.fr\/forcats-forcats-vous-avez-dit-forcats\/\">ici<\/a>, sur le blog de ThinkR, que \u00e7a se passe.<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/forcats.png\" alt=\"\" \/><\/p>\n<p>Chargeons de ce pas <code>forcats<\/code>, avant de d\u00e9composer les diff\u00e9rents \u00e9l\u00e9ments de cette figure&#8230;<\/p>\n<pre><code>library(forcats)\n<\/code><\/pre>\n<h1>Cr\u00e9er des factors<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/create_factors.png\" alt=\"\" \/><\/p>\n<p>On peut cr\u00e9er un factor \u00e0 l&rsquo;aide de la fonction <code>factor()<\/code> (pour le coup il ne s&rsquo;agit pas d&rsquo;une fonction de <code>forcats<\/code> mais d&rsquo;une fonction de <code>base<\/code>).<\/p>\n<p>Par d\u00e9faut, quand on cr\u00e9e un factor \u00e0 partir d&rsquo;un vecteur, les niveaux sont cr\u00e9\u00e9s en consid\u00e9rant l&rsquo;ensemble des valeurs uniques de ce vecteur.<\/p>\n<pre><code>vecteur=c(\"b\",\"a\",\"c\",\"a\",\"d\",\"c\",\"d\",\"d\",\"d\",\"b\",\"d\",\"a\")\nf1=factor(vecteur)\nprint(f1)\n\n##  [1] b a c a d c d d d b d a\n## Levels: a b c d\n<\/code><\/pre>\n<p>Notez que les niveaux du factor sont ordonn\u00e9s par d\u00e9faut par ordre alphab\u00e9tique.<\/p>\n<p>Il est possible que certaines valeurs possibles pour ce factor soient absentes du vecteur, auquel cas on peut sp\u00e9cifier l&rsquo;ensemble des valeurs prises de la mani\u00e8re suivante:<\/p>\n<pre><code>f2= factor(vecteur, levels=c(\"a\",\"b\",\"c\",\"d\",\"e\"))\nprint(f2)\n\n##  [1] b a c a d c d d d b d a\n## Levels: a b c d e\n<\/code><\/pre>\n<h1>Changement des noms de niveaux<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/change_names.png\" alt=\"\" \/><\/p>\n<p>Si l&rsquo;on souhaite modifier les noms de niveaux, on peut proc\u00e9der de deux mani\u00e8res:<\/p>\n<ul>\n<li>soit en changeant l&rsquo;<strong>ensemble des noms de niveaux<\/strong> d&rsquo;un coup, avec la fonction <code>levels()<\/code> de <code>base<\/code><\/li>\n<li>soit en choisissant <strong>sp\u00e9cifiquement le niveau<\/strong> qu&rsquo;on souhaite modifier, \u00e0 l&rsquo;aide de la fonction <code>fct_recode()<\/code> de <code>forcats<\/code><\/li>\n<\/ul>\n<p>Dans les deux cas, bien s\u00fbr, le nom n&rsquo;est pas seulement modifi\u00e9 dans la partie \u00ab\u00a0levels\u00a0\u00bb du factor, mais \u00e9galement dans les valeurs m\u00eames.<\/p>\n<pre><code>f1\n\n##  [1] b a c a d c d d d b d a\n## Levels: a b c d\n\nf2=f1\nlevels(f2)=c(\"tagada\",\"pouetpouet\",\"tsointsoin\",\"boum\")\nf2\n\n##  [1] pouetpouet tagada     tsointsoin tagada     boum       tsointsoin boum       boum       boum       pouetpouet boum       tagada    \n## Levels: tagada pouetpouet tsointsoin boum\n\nf2=fct_recode(f1, tsointsoin=\"c\")\nf2\n\n##  [1] b          a          tsointsoin a          d          tsointsoin d          d          d          b          d          a         \n## Levels: a b tsointsoin d\n<\/code><\/pre>\n<h1>Changement de l&rsquo;ordre des niveaux<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/change_order.png\" alt=\"\" \/><\/p>\n<p>Plusieurs fonctions permettent de r\u00e9ordonner les niveaux.<\/p>\n<ul>\n<li><code>fct_rev()<\/code> permet d&rsquo;<strong>inverser<\/strong> l&rsquo;ordre des niveaux<\/li>\n<li><code>fct_relevel()<\/code> permet de <strong>sp\u00e9cifier le rang<\/strong> d&rsquo;un ou plusieurs niveaux sp\u00e9cifiques<\/li>\n<li><code>fct_inorder()<\/code> permet de ranger les niveaux selon leur <strong>ordre d&rsquo;apparition dans la s\u00e9rie de valeurs<\/strong><\/li>\n<li><code>fct_infreq()<\/code> permet de ranger les niveaux selon leur <strong>ordre (d\u00e9croissant) de fr\u00e9quence<\/strong>.<\/li>\n<\/ul>\n<p><!-- --><\/p>\n<pre><code>fct_rev(f1) #inverse les niveaux\n\n##  [1] b a c a d c d d d b d a\n## Levels: d c b a\n\nfct_relevel(f1,\"c\") #remonte \"c\" en t\u00eate\n\n##  [1] b a c a d c d d d b d a\n## Levels: c a b d\n\nfct_relevel(f1,\"c\",\"d\") #remonte \"c\" et \"d\" en t\u00eate\n\n##  [1] b a c a d c d d d b d a\n## Levels: c d a b\n\nfct_relevel(f1,\"a\",after=2) #place a en 3i\u00e8me position \n\n##  [1] b a c a d c d d d b d a\n## Levels: b c a d\n\nfct_inorder(f1) # ordre d'apparition: b appara\u00eet en premier, puis a, etc.\n\n##  [1] b a c a d c d d d b d a\n## Levels: b a c d\n\nfct_infreq(f1) # ordre de fr\u00e9quence: d est le plus fr\u00e9quent, puis a, etc.\n\n##  [1] b a c a d c d d d b d a\n## Levels: d a b c\n<\/code><\/pre>\n<h1>Agr\u00e9gation des niveaux rares en un seul niveau<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/aggregate_levels.png\" alt=\"\" \/> Dans certains cas, les effectifs des diff\u00e9rents niveaux peuvent \u00eatre tr\u00e8s d\u00e9sequilibr\u00e9s. Dans ce cas, il peut \u00eatre utile de r\u00e9agr\u00e9ger un certain nombre de niveaux rares en un seul niveau. C&rsquo;est ce que permet la fonction <code>fct_lump()<\/code>.<\/p>\n<pre><code>vecteur=c(rep(\"a\",9),rep(\"b\",6),rep(\"c\",3),\"d\",\"e\")[sample(1:20, 20, replace=FALSE)]\nf3=factor(vecteur)\nf3\n\n##  [1] b a a a b a a a c c b d b e a c b a a b\n## Levels: a b c d e\n<\/code><\/pre>\n<p>Les effectifs sont r\u00e9partis comme suit:<\/p>\n<pre><code>table(f3)\n\n## f3\n## a b c d e \n## 9 6 3 1 1\n<\/code><\/pre>\n<p>La fonction fct_lump peut r\u00e9agr\u00e9ger les niveaux moins fr\u00e9quent (\u00ab\u00a0c\u00a0\u00bb,\u00a0\u00bbd\u00a0\u00bb, et \u00ab\u00a0e\u00a0\u00bb) en un seul niveau \u00ab\u00a0Other\u00a0\u00bb:<\/p>\n<pre><code>fct_lump(f3)\n\n##  [1] b     a     a     a     b     a     a     a     Other Other b     Other b     Other a     Other b     a     a     b    \n## Levels: a b Other\n<\/code><\/pre>\n<p>Bien entendu, il est possible de param\u00e9trer cette fonction pour d\u00e9finir plus <strong>explicitement les seuils de fr\u00e9quence ou de proportion<\/strong> que l&rsquo;on utilise pour d\u00e9finir quels niveaux sont consid\u00e9r\u00e9s comme <strong>peu fr\u00e9quents<\/strong>.<\/p>\n<pre><code>fct_lump(f3, n=3) # niveaux rares= effectif &lt; 3\n\n##  [1] b     a     a     a     b     a     a     a     c     c     b     Other b     Other a     c     b     a     a     b    \n## Levels: a b c Other\n\nfct_lump(f3, prop=0.15) # niveaux rares= proportion &lt; 15%\n\n##  [1] b     a     a     a     b     a     a     a     Other Other b     Other b     Other a     Other b     a     a     b    \n## Levels: a b Other\n\nfct_lump(f3, other_level=\"autre\") # nom du nouveau niveau\n\n##  [1] b     a     a     a     b     a     a     a     autre autre b     autre b     autre a     autre b     a     a     b    \n## Levels: a b autre\n<\/code><\/pre>\n<h1>Changement d&rsquo;ordre en vue d&rsquo;une production graphique<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/reorder_for_plot.png\" alt=\"\" \/> Quand on produit des graphiques impliquant une variable cat\u00e9gorielle, il peut \u00eatre utile d&rsquo;<strong>ajuster la position\/les niveaux<\/strong> des points\/barres\/bo\u00eetes \u00e0 moustaches de mani\u00e8re \u00e0 rendre le graphique le plus lisible possible.<\/p>\n<p>Sans <code>fct_reorder()<\/code>:<\/p>\n<pre><code>catdata= read.csv(url(\"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/Rdata\/Graphiques_avec_ggplot2\/catdata.csv\"), sep=\";\")\nlibrary(ggplot2)\nggplot(catdata, aes(x=haircolor, y=weight)) +\n  geom_boxplot(fill=\"yellow\")\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/boxplot_sans-1.png\" alt=\"\" \/><\/p>\n<p>Avec <code>fct_reorder()<\/code>:<\/p>\n<pre><code>ggplot(catdata, aes(x=fct_reorder(haircolor,weight), y=weight)) +\n  geom_boxplot(fill=\"yellow\")\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/boxplot_avec-1.png\" alt=\"\" \/> Les niveaux sont ordonn\u00e9s par ordre croissant de m\u00e9diane de <code>weight<\/code> (<code>median()<\/code> est la fonction utilis\u00e9e par d\u00e9faut par <code>fct_reorder()<\/code> mais il est possible d&rsquo;en changer en utilisant l&rsquo;argument <code>fun=...<\/code>) .<\/p>\n<p>Autre exemple, les effectifs:<\/p>\n<p>Sans <code>fct_reorder()<\/code>:<\/p>\n<pre><code>ggplot(catdata, aes(x=haircolor)) +\n  geom_bar(aes(fill=sex))\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/barplot_sans-1.png\" alt=\"\" \/><\/p>\n<p>Avec <code>fct_reorder()<\/code>:<\/p>\n<pre><code>ggplot(catdata, aes(x=fct_reorder(haircolor, sex, fun=length, .desc=TRUE))) +\n  geom_bar(aes(fill=sex))\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/forcats\/barplot_avec-1.png\" alt=\"\" \/><\/p>\n<p>Les niveaux de <code>haircolor<\/code> sont r\u00e9organis\u00e9s par ordre (ici, l&rsquo;ordre d\u00e9croissant du fait de l&rsquo;argument <code>.desc=TRUE<\/code>) de fr\u00e9quence.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>J&rsquo;ai r\u00e9cemment eu \u00e0 travailler avec des donn\u00e9es d&rsquo;enqu\u00eate (ce qui m&rsquo;arrive somme toute assez rarement) et notamment \u00e0 tenter de produire des tableaux et des figures rendant compte de ces donn\u00e9es, souvent cat\u00e9gorielles. J&rsquo;ai \u00e9t\u00e9 assez rapidement confront\u00e9e \u00e0 un probl\u00e8me qui peut sembler trivial de prime abord, mais qui n\u00e9anmoins n&rsquo;est pas si anecdotique que cela au regard du temps qu&rsquo;il peut faire perdre: la manipulation de factors,.. <a href=\"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/manipulation-de-facteurs-avec-forcats\/\">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-852","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\/852","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=852"}],"version-history":[{"count":15,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/852\/revisions"}],"predecessor-version":[{"id":867,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/852\/revisions\/867"}],"wp:attachment":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/media?parent=852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/categories?post=852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/tags?post=852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}