{"id":899,"date":"2018-02-13T15:26:54","date_gmt":"2018-02-13T14:26:54","guid":{"rendered":"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=899"},"modified":"2018-03-21T11:23:25","modified_gmt":"2018-03-21T10:23:25","slug":"iterer-des-fonctions-avec-purrr","status":"publish","type":"post","link":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/iterer-des-fonctions-avec-purrr\/","title":{"rendered":"It\u00e9ration de fonctions avec purrr"},"content":{"rendered":"<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/Lise_Vaudor_headband-1.png\" alt=\"\" \/><\/p>\n<p>Bon, les amis, je vais \u00eatre abrupte, mais voil\u00e0:<\/p>\n<p>Les boucles sont officiellement <em>has been<\/em> depuis le printemps-\u00e9t\u00e9 2017. Non, je ne parle pas des boucles soyeuses et joyeuses qui s&rsquo;\u00e9battent sur vos t\u00eates (pour les plus chanceux d&rsquo;entre vous). Je veux parler des boucles laborieuses et \u00e9pineuses qui s&rsquo;\u00e9tirent sur vos scripts.<\/p>\n<p>Alors, je me sens quand-m\u00eame l\u00e9g\u00e8rement g\u00ean\u00e9e de vous annoncer cela vu que, peut-\u00eatre, vous avez r\u00e9cemment appris \u00e0 faire des boucles et vous vous en trouvez fort aise (moi aussi, je me souviens, quand j&rsquo;ai fait mes premi\u00e8res boucles, de la joie, de la fiert\u00e9 \u00e9prouv\u00e9e, de la conviction vibrante que j&rsquo;allais d\u00e9sormais dire adieu aux assommantes t\u00e2ches r\u00e9p\u00e9titives). Peut-\u00eatre que mentionner la ringardise des boucles devant des gens qui apprennent \u00e0 utiliser R, c&rsquo;est comme annoncer \u00e0 un ado tout fier des ses trois premiers poils de moustache que bon, c&rsquo;est pas tr\u00e8s joli et qu&rsquo;il va falloir raser tout \u00e7a. Je pr\u00e9cise donc, au cas o\u00f9 cette id\u00e9e vous d\u00e9moralise trop, qu&rsquo;un peu de ringardise n&rsquo;a jamais fait de mal \u00e0 personne et que vous pouvez choisir de voir vos bonnes vieilles boucles for de derri\u00e8re les fagots comme une touche \u00ab\u00a0vintage\u00a0\u00bb dans vos scripts (et nous ne sommes pas l\u00e0 pour juger!).<\/p>\n<p>Concr\u00e8tement, la boucle for n&rsquo;a pas le vent en poupe pour plusieurs raisons: elle est assez longue \u00e0 \u00e9crire, elle peut donner lieu \u00e0 pas mal d&rsquo;erreurs (elle est \u00ab\u00a0error-prone\u00a0\u00bb, comme diraient les anglophones), et elle n&rsquo;est pas tr\u00e8s efficace en termes de calcul (ce dernier argument pouvant rev\u00eatir une importance plus ou moins av\u00e9r\u00e9e selon que vos scripts sont calculatoirement gourmands ou non).<\/p>\n<p>Notez aussi que, non contentes de remplacer les boucles for, les fonctions de <code>purrr<\/code> sont aussi susceptibles de remplacer dans vos scripts les fonctions <code>apply()<\/code>, <code>tapply()<\/code>, <code>sapply()<\/code> et consorts&#8230;<\/p>\n<p>Mais venons-en au fait, \u00e0 savoir <em>ce qui est cens\u00e9 remplacer les boucles for<\/em> (parce que quand-m\u00eame, savoir it\u00e9rer une t\u00e2che, une routine, un script, \u00e7a reste un must), \u00e0 savoir, les fonctions du package <strong>purrr<\/strong>.<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/purrr.png\" alt=\"\" \/><\/p>\n<h1>Principe g\u00e9n\u00e9ral<\/h1>\n<p><strong>purrr<\/strong>, c&rsquo;est un package du <strong>tidyverse<\/strong> (qui compte d&rsquo;autres packages ultra-connus et appr\u00e9ci\u00e9s comme dplyr, ggplot2, lubridate, etc.) qui sert \u00e0 <strong>it\u00e9rer des fonctions<\/strong>. C&rsquo;est une package qui s&rsquo;inscrit un peu dans la logique de la programmation fonctionnelle, c&rsquo;est-\u00e0-dire dans l&rsquo;id\u00e9e que tout ce qui <em>arrive<\/em> dans R est le r\u00e9sultat d&rsquo;un appel \u00e0 une fonction (alors que ce qui <em>existe<\/em> dans R est un objet). Pour rendre \u00e0 C\u00e9sar ce qui revient \u00e0 C\u00e9sar, je reprends l\u00e0 les mots de John Chambers: \u201cTo understand computations in R, two slogans are helpful: Everything that exists is an object. Everything that happens is a function call.\u00a0\u00bb.<\/p>\n<h1>Fonctions: inputs, output, side effects<\/h1>\n<p>Voil\u00e0 comment on peut voir une fonction&#8230;<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/purrr1.png\" alt=\"\" \/><\/p>\n<p>&#8230; comme une petite usine qui transforme ses mati\u00e8res premi\u00e8res (les <strong>inputs<\/strong>, ou arguments) en produits finis (les <strong>outputs<\/strong>), en g\u00e9n\u00e9rant parfois au passage des effets \u00ab\u00a0immat\u00e9riels\u00a0\u00bb -c&rsquo;est-\u00e0-dire autres que des objets- ici repr\u00e9sent\u00e9s par de la fum\u00e9e (les <strong>side effects<\/strong>).<\/p>\n<p>Ici je consid\u00e8re une fonction <code>.f()<\/code> qui a un input principal <code>x<\/code> et des inputs secondaires (<code>...<\/code>). Classiquement, on va produire l&rsquo;output en appelant la fonction avec pour arguments l&rsquo;input <code>x<\/code> et les inputs secondaires: <code>output=.f(x,...)<\/code>.<\/p>\n<p>Par exemple:<\/p>\n<pre><code>x=c(33,NA,2,15,7,4,5)\nmoyenne=mean(x,na.rm=TRUE)\n<\/code><\/pre>\n<p>Ici, j&rsquo;ai produit l&rsquo;output <code>moyenne<\/code> en appelant la fonction <code>mean()<\/code>, avec pour argument principal <code>x<\/code> et pour argument secondaire <code>na.rm=TRUE<\/code>.<\/p>\n<h1>It\u00e9ration: map(), walk()<\/h1>\n<p>Imaginons maintenant que je souhaite appeler la fonction <code>mean()<\/code> de mani\u00e8re r\u00e9p\u00e9t\u00e9e sur plusieurs \u00e9l\u00e9ments d&rsquo;une liste:<\/p>\n<pre><code>myX=list(c(33,NA,2,15,7,4,5),\n         c(22,1,3,NA,11,2),\n         c(1,5),\n         c(3),\n         c(12,5,9))\n<\/code><\/pre>\n<p>Je pourrais choisir de le faire via une boucle for \u00ab\u00a0vintage\u00a0\u00bb:<\/p>\n<pre><code>moyennes=vector(\"list\",length=5)\nfor (i in 1:length(myX)){\n  moyennes[i]=mean(myX[[i]],na.rm=TRUE)\n}\nprint(moyennes)\n\n## [[1]]\n## [1] 11\n## \n## [[2]]\n## [1] 7.8\n## \n## [[3]]\n## [1] 3\n## \n## [[4]]\n## [1] 3\n## \n## [[5]]\n## [1] 8.666667\n<\/code><\/pre>\n<p>OU BIEN je peux choisir de le faire avec la fonction <code>map()<\/code> du package <code>purrr<\/code><\/p>\n<pre><code>library(purrr)\nmoyennes=map(myX,mean, na.rm=TRUE)\nprint(moyennes)\n\n## [[1]]\n## [1] 11\n## \n## [[2]]\n## [1] 7.8\n## \n## [[3]]\n## [1] 3\n## \n## [[4]]\n## [1] 3\n## \n## [[5]]\n## [1] 8.666667\n<\/code><\/pre>\n<p>Ainsi, en utilisant <code>map()<\/code>, j&rsquo;ai en quelque sorte transform\u00e9 ma petite fonction\/usine <code>mean()<\/code> en lui adjoignant une <strong>\u00ab\u00a0rampe d&rsquo;approvisionnement\u00a0\u00bb<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/purrr2.png\" alt=\"\" \/><\/p>\n<p>Mon argument principal, <code>x<\/code>, devient ainsi une <strong>liste<\/strong> d&rsquo;\u00e9l\u00e9ments utilis\u00e9s comme input pour la fonction <code>mean()<\/code>. Mon argument secondaire, <code>na.rm=TRUE<\/code>, est en revanche le m\u00eame pour toutes les it\u00e9rations.<\/p>\n<p>L&rsquo;output \u00ab\u00a0moyennes\u00a0\u00bb est par d\u00e9faut \u00e9galement une <strong>liste<\/strong>.<\/p>\n<p>Notez que l&rsquo;on aurait pu ici demander explicitement \u00e0 ce que le r\u00e9sultat nous soit renvoy\u00e9 non pas comme une liste, mais comme un <strong>vecteur de valeurs num\u00e9riques de type \u00ab\u00a0double\u00a0\u00bb<\/strong>:<\/p>\n<pre><code>moyennes=map_dbl(x,mean,na.rm=TRUE)\nprint(moyennes)\n\n## [1]  33 NaN   2  15   7   4   5\n<\/code><\/pre>\n<p>Selon le type d&rsquo;output renvoy\u00e9 par la fonction, il peut ainsi \u00eatre assez pratique d&rsquo;utiliser les fonctions <code>map_dbl()<\/code> (double) <code>map_lgl<\/code> (logique) <code>map_int()<\/code> (entier), etc.<\/p>\n<p>Consid\u00e9rons maintenant les \u00ab\u00a0effets secondaires\u00a0\u00bb\u00a0\u00bb, en prenant pour exemple une fonction dont l&rsquo;utilit\u00e9 premi\u00e8re n&rsquo;est pas de renvoyer un output, mais plut\u00f4t d&rsquo;afficher quelque chose dans la console:<\/p>\n<pre><code>print_moyenne=function(x){\n  print(paste(\"la moyenne est de\",\n              mean(x,na.rm=TRUE)))\n  return(NULL)\n}\n<\/code><\/pre>\n<p>La fonction \u00ab\u00a0walk()\u00a0\u00bb permet d&rsquo;it\u00e9rer les \u00ab\u00a0effets secondaires\u00a0\u00bb d&rsquo;une fonction&#8230; ici 5 messages\/nuages de fum\u00e9e diff\u00e9rents:<\/p>\n<pre><code>walk(x,print_moyenne)\n\n## [1] \"la moyenne est de 33\"\n## [1] \"la moyenne est de NaN\"\n## [1] \"la moyenne est de 2\"\n## [1] \"la moyenne est de 15\"\n## [1] \"la moyenne est de 7\"\n## [1] \"la moyenne est de 4\"\n## [1] \"la moyenne est de 5\"\n<\/code><\/pre>\n<h1>2 arguments principaux: map2()<\/h1>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/purrr3.png\" alt=\"\" \/><\/p>\n<p>Consid\u00e9rons maintenant une fonction \u00e0 laquelle on voudrait adjoindre \u00ab\u00a0deux rampes d&rsquo;approvisionnement\u00a0\u00bb:<\/p>\n<pre><code>reg=function(x,y,w=rep(1,length(x))){\n  result=lm(y~x,weights=w)\n  return(result)\n}\n<\/code><\/pre>\n<p>Cette fonction <code>reg()<\/code> r\u00e9alise une r\u00e9gression lin\u00e9aire de y en fonction de x (avec des poids uniformes, par d\u00e9faut) et renvoie l&rsquo;objet \u00ab\u00a0r\u00e9gression lin\u00e9aire\u00a0\u00bb correspondant (l&rsquo;output de <code>reg()<\/code> est donc un objet \u00ab\u00a0composite\u00a0\u00bb de type liste).<\/p>\n<pre><code>myX=list(c(2,5,6,7,1,0,1,1),\n       c(5,1,6,NA,2),\n       c(2,5,8,6))\nmyY=list(c(5,8,9,7,22,1,9,9),\n       c(2,8,9,5,4),\n       c(8,9,8,7))\n<\/code><\/pre>\n<p>On veut it\u00e9rer la fonction <code>reg()<\/code> en consid\u00e9rant chaque \u00e9l\u00e9ment de x ET de y (le i-i\u00e8me \u00e9l\u00e9ment de x correspondant au i-i\u00e8me \u00e9l\u00e9ment de y&#8230;). On peut faire cela en consid\u00e9rant la fonction <code>map2()<\/code>.<\/p>\n<pre><code>map2(myX,myY,reg)\n\n## [[1]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      9.2162      -0.1622  \n## \n## \n## [[2]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##     5.85294     -0.02941  \n## \n## \n## [[3]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##     8.28000     -0.05333\n<\/code><\/pre>\n<p>Notez ici que la fonction <code>reg()<\/code> renvoie une liste donc ce n&rsquo;est pas pertinent ici d&rsquo;essayer d&rsquo;utiliser une fonction de type map_xxx() (en l&rsquo;\u00e9tat, le r\u00e9sultat de l&rsquo;it\u00e9ration ne peut pas \u00eatre mis en forme comme un vecteur).<\/p>\n<h1>p arguments principaux: pmap()<\/h1>\n<p>Enfin, on peut g\u00e9n\u00e9raliser ce principe \u00e0 <em>p<\/em>\u2004>\u20042 arguments principaux:<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/purrr4.png\" alt=\"\" \/><\/p>\n<p>Dans ce cas, les p listes d&rsquo;arguments sont fournis comme une liste, i.e. on passe \u00e0 <code>pmap()<\/code> un argument <code>.l<\/code> qui est une <strong>liste de p \u00e9l\u00e9ments<\/strong> <em>qui sont eux-m\u00eames des listes<\/em>&#8230;<\/p>\n<p>Consid\u00e9rons par exemple un cas o\u00f9 l&rsquo;on souhaite it\u00e9rer la fonction <code>reg()<\/code>, consid\u00e9r\u00e9e pr\u00e9c\u00e9demment, mais cette fois-ci sur 3 arguments, \u00e0 savoir x, y, et w:<\/p>\n<pre><code>myW=list(c(1,2,1,1,1,2,1,1),\n         c(2,1,1,1,1),\n         c(1,2,1,1))\n\npmap(list(x=myX,\n          y=myY,\n          w=myW),\n     reg)\n\n## [[1]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      7.3805       0.1855  \n## \n## \n## [[2]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##       6.011       -0.266  \n## \n## \n## [[3]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##     8.53191     -0.06383\n<\/code><\/pre>\n<h1>Echapper aux erreurs: <code>safely()<\/code><\/h1>\n<p>Jusqu&rsquo;ici, tout va bien: j&rsquo;ai choisi pour commencer des exemples d&rsquo;application simples, o\u00f9 tout se d\u00e9roule comme sur des roulettes.<\/p>\n<p>Mais avec les fonctions de <code>purrr<\/code> comme avec une boucle for, il est particuli\u00e8rement probl\u00e9matique qu&rsquo;une des it\u00e9rations g\u00e9n\u00e8re une <strong>erreur<\/strong>, car m\u00eame si cette erreur ne concerne qu&rsquo;un \u00e9l\u00e9ment parmi peut-\u00eatre beaucoup d&rsquo;autres, son occurrence stoppe l&rsquo;ex\u00e9cution de <em>toutes<\/em> les it\u00e9rations.<\/p>\n<p>Consid\u00e9rons ainsi l&rsquo;exemple suivant:<\/p>\n<pre><code>myX=list(c(2,5,6,7,1,0,1,1),\n         c(5,1,6,NA,2),\n         c())\nmyY=list(c(5,8,9,7,22,1,9,9),\n         c(2,8,9,5,4),\n         c())\nmap2(myX,myY,reg)\n\n## Error in model.frame.default(formula = y ~ x, weights = w, drop.unused.levels = TRUE): type (NULL) incorrect pour la variable 'y'\n<\/code><\/pre>\n<p>A\u00efe&#8230; La fonction reg n&rsquo;accepte pas que ses arguments x ou y soient nuls et g\u00e9n\u00e8re ainsi une erreur sur la troisi\u00e8me it\u00e9ration. On n&rsquo;obtient donc pas de r\u00e9sultat pour la troisi\u00e8me it\u00e9ration, ni, du reste, pour les autres&#8230;<\/p>\n<p>Pour rem\u00e9dier \u00e0 cela, outre modifier la fonction <code>reg()<\/code> pour qu&rsquo;elle puisse s&rsquo;adapter \u00e0 ce cas particulier, il est possible d&rsquo;utiliser la fonction <code>safely()<\/code>:<\/p>\n<pre><code>map2(myX,myY,safely(reg))\n\n## [[1]]\n## [[1]]$result\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      9.2162      -0.1622  \n## \n## \n## [[1]]$error\n## NULL\n## \n## \n## [[2]]\n## [[2]]$result\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##     5.85294     -0.02941  \n## \n## \n## [[2]]$error\n## NULL\n## \n## \n## [[3]]\n## [[3]]$result\n## NULL\n## \n## [[3]]$error\n## &lt;simpleError in model.frame.default(formula = y ~ x, weights = w, drop.unused.levels = TRUE): type (NULL) incorrect pour la variable 'y'&gt;\n<\/code><\/pre>\n<p>Dans ce cas, pour chaque \u00e9l\u00e9ment d&rsquo;input, on obtient un \u00e9l\u00e9ment d&rsquo;output qui contient deux choses:<\/p>\n<ul>\n<li>un \u00e9l\u00e9ment <code>result<\/code> (qui correspond au r\u00e9sultat souhait\u00e9 et est dans ce cas vide pour le troisi\u00e8me \u00e9l\u00e9ment, probl\u00e9matique)<\/li>\n<li>un \u00e9l\u00e9ment <code>error<\/code> (qui correspond \u00e0 l&rsquo;\u00e9ventuel message d&rsquo;erreur g\u00e9n\u00e9r\u00e9 et est dans ce cas vide pour les deux premiers \u00e9l\u00e9ments, qui ne g\u00e9n\u00e8rent pas d&rsquo;erreur)<\/li>\n<\/ul>\n<h1>Manipulation des listes<\/h1>\n<p>Vous l&rsquo;avez vu, <code>purrr<\/code> fait beaucoup appel \u00e0 des objets de type liste, que ce soit en argument d&rsquo;entr\u00e9e ou en sortie. Il peut donc \u00eatre utile de vous donner ou redonner quelques rep\u00e8res pour manipuler ces listes sans que cela vous cause trop d&rsquo;inconfort&#8230;<\/p>\n<p>Reprenons ainsi le r\u00e9sultat g\u00e9n\u00e9r\u00e9 pr\u00e9c\u00e9demment:<\/p>\n<pre><code>myRegs=map2(myX,myY,safely(reg))\n<\/code><\/pre>\n<p>On peut r\u00e9cup\u00e9rer un \u00e9l\u00e9ment de cette liste de la mani\u00e8re suivante (attention, des crochets simples r\u00e9cup\u00e9reraient une liste de longueur 1 <em>contenant<\/em> l&rsquo;objet issu de <code>reg()<\/code>, et non l&rsquo;objet issu de <code>reg()<\/code> directement):<\/p>\n<pre><code>myRegs[[1]]\n\n## $result\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      9.2162      -0.1622  \n## \n## \n## $error\n## NULL\n<\/code><\/pre>\n<p>On peut ensuite acc\u00e9der aux \u00e9l\u00e9ments de myRegs[<a href=\"..\/..\/lise.vaudor\/Rfigures\/Purrr\/Lise_Vaudor_headband-1.png\">1<\/a>] soit en utilisant leur nom (ici <code>result<\/code> ou <code>error<\/code>) soit en utilisant leur index (ici 1 ou 2)<\/p>\n<pre><code>myRegs[[1]]$result # idem: myRegs[[1]][1]\n\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      9.2162      -0.1622\n<\/code><\/pre>\n<p>&#8230; et si, pour chacun des 3 \u00e9l\u00e9ments de <code>myRegs<\/code>, je veux r\u00e9cup\u00e9rer l&rsquo;\u00e9l\u00e9ment <code>result<\/code>, eh bien, l\u00e0 encore, la fonction <code>map()<\/code> peut me servir:<\/p>\n<pre><code>map(myRegs,\"result\")\n\n## [[1]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##      9.2162      -0.1622  \n## \n## \n## [[2]]\n## \n## Call:\n## lm(formula = y ~ x, weights = w)\n## \n## Coefficients:\n## (Intercept)            x  \n##     5.85294     -0.02941  \n## \n## \n## [[3]]\n## NULL\n<\/code><\/pre>\n<p>Attention, notez bien la diff\u00e9rence de syntaxe:<\/p>\n<pre><code>map(x,\"pouetpouet\")\n<\/code><\/pre>\n<p>cherche \u00e0 <strong>extraire un \u00e9l\u00e9ment<\/strong> appel\u00e9 \u00ab\u00a0pouetpouet\u00a0\u00bb des diff\u00e9rents \u00e9l\u00e9ments de la liste <code>x<\/code>.<\/p>\n<p>En revanche<\/p>\n<pre><code>map(x,pouetpouet)\n<\/code><\/pre>\n<p>cherche \u00e0 <strong>appliquer une fonction<\/strong> appel\u00e9e <code>pouetpouet<\/code> aux diff\u00e9rents \u00e9l\u00e9ments de la liste <code>x<\/code><\/p>\n<p>Enfin, notons que le package <code>purrr<\/code> partage une caract\u00e9ristique sympathique de ses petits coll\u00e8gues de tidyverse, \u00e0 savoir la compatibilit\u00e9 avec le \u00ab\u00a0<strong>piping<\/strong>\u00ab\u00a0. On peut ainsi encha\u00eener facilement diff\u00e9rents appels \u00e0 ses fonctions. Par exemple:<\/p>\n<pre><code>map2(myX,myY,safely(reg)) %&gt;%   #On it\u00e8re la fonction reg()\n  map(\"result\") %&gt;%            #On r\u00e9cup\u00e8re l'\u00e9l\u00e9ment \"result\" \n  map(\"coefficients\") %&gt;%      #On r\u00e9cup\u00e8re l'\u00e9l\u00e9ment \"coefficients\"\n  map(2)                       #On r\u00e9cup\u00e8re le deuxi\u00e8me \u00e9l\u00e9mnent de ce tableau\n\n## [[1]]\n## [1] -0.1621622\n## \n## [[2]]\n## [1] -0.02941176\n## \n## [[3]]\n## NULL\n\n#On obtient ainsi les pentes des r\u00e9gressions\n<\/code><\/pre>\n<p>Enfin, une petite commande qui peut s&rsquo;av\u00e9rer pratique si l&rsquo;on veut revenir \u00e0 des donn\u00e9es tabulaires :<\/p>\n<pre><code>myCoeffs=map(myRegs,\"result\") %&gt;%\n  map(\"coefficients\")\nprint(myCoeffs)\n\n## [[1]]\n## (Intercept)           x \n##   9.2162162  -0.1621622 \n## \n## [[2]]\n## (Intercept)           x \n##  5.85294118 -0.02941176 \n## \n## [[3]]\n## NULL\n\ndo.call(\"rbind\",myCoeffs)\n\n##      (Intercept)           x\n## [1,]    9.216216 -0.16216216\n## [2,]    5.852941 -0.02941176\n<\/code><\/pre>\n<p>En effet, <code>do.call()<\/code> permet de \u00ab\u00a0redispatcher\u00a0\u00bb les \u00e9l\u00e9ments d&rsquo;une liste comme autant d&rsquo;arguments d&rsquo;entr\u00e9e d&rsquo;une fonction, c&rsquo;est-\u00e0-dire qu&rsquo;il permet d&rsquo;utiliser myCoeffs (qui correspond \u00e0 la liste des arguments <code>myCoeffs=list(arg1,arg2,arg3)<\/code>) pour appeler <code>rbind()<\/code>, alors que classiquement, <code>rbind()<\/code> devrait s&rsquo;appeler de la mani\u00e8re suivante :<\/p>\n<pre><code>rbind(arg1,arg2,arg3)\n<\/code><\/pre>\n<h1>Un mot d&rsquo;encouragement ?<\/h1>\n<p>Je ne sais pas si vous \u00eates d\u00e9j\u00e0 convaincus, alors je vais en rajouter une couche: oui, les fonctions de <code>purrr<\/code> peuvent vous simplifier la vie, m\u00eame si, oui, c&rsquo;est une gymnastique intellectuelle au d\u00e9but&#8230;<\/p>\n<p>Si vous comprenez bien l&rsquo;usage des fonctions, et que vous prenez l&rsquo;habitude d&rsquo;utiliser des listes, ce package pourrait bien devenir une seconde nature&#8230; Et \u00e7a n&#8217;emp\u00eache pas de s&rsquo;autoriser un petit plaisir r\u00e9tro de temps en temps en \u00e9crivant une boucle for, de la m\u00eame mani\u00e8re qu&rsquo;on a le droit d&rsquo;\u00e9couter des vinyles, d&rsquo;aimer les plats mijot\u00e9s, ou de porter la moustache en 2018.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bon, les amis, je vais \u00eatre abrupte, mais voil\u00e0: Les boucles sont officiellement has been depuis le printemps-\u00e9t\u00e9 2017. Non, je ne parle pas des boucles soyeuses et joyeuses qui s&rsquo;\u00e9battent sur vos t\u00eates (pour les plus chanceux d&rsquo;entre vous). Je veux parler des boucles laborieuses et \u00e9pineuses qui s&rsquo;\u00e9tirent sur vos scripts. Alors, je me sens quand-m\u00eame l\u00e9g\u00e8rement g\u00ean\u00e9e de vous annoncer cela vu que, peut-\u00eatre, vous avez r\u00e9cemment.. <a href=\"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/iterer-des-fonctions-avec-purrr\/\">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-899","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\/899","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=899"}],"version-history":[{"count":5,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/899\/revisions"}],"predecessor-version":[{"id":904,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/899\/revisions\/904"}],"wp:attachment":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/media?parent=899"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/categories?post=899"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/tags?post=899"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}