- Le blog participatif de bioinformatique francophone depuis 2012 -

Guide de démarrage pour ggplot2, un package graphique pour R

ggplot2
Had­ley Wick­ham signed his book "ggplot2" in my iPad | H. Oku­mu­ra

Le trai­te­ment et l’analyse de don­nées sont une part impor­tante des tâches deman­dées à un bio­in­for­ma­ti­cien. L’utilisation de R faci­lite gran­de­ment la mani­pu­la­tion des don­nées et per­met éga­le­ment leur repré­sen­ta­tion de mul­tiples façons. Mal­gré le poten­tiel de R, ce der­nier est sou­vent sous-exploi­té à cause d’une syn­taxe par­fois trop com­plexe. Je vais vous pré­sen­ter aujourd’hui un package R, « ggplot2 », per­met­tant la pro­duc­tion de gra­phiques très éla­bo­rés en peu de temps.

Un peu d’histoire

Ggplot2 est un "package" R créé par Had­ley Wick­ham en 2005. Pour ceux qui ne le connaî­traient pas, Had­ley Wick­ham est un peu le dieu de R depuis quelques années. Il est à la base de "packages" faci­li­tant la vie des uti­li­sa­teurs de R tels que ‘plyr’, ‘reshape2’, ‘lubri­date’, ‘strin­gr’, ‘tes­J­hat’. Vous pou­vez en apprendre plus sur Had­ley Wick­ham ici. Ggplot2 s’inspire en par­tie des tra­vaux de Leland Wil­kin­son décrits dans « Gram­mar of Gra­phics — a gene­ral scheme for data visua­li­za­tion which breaks up graphs into seman­tic com­po­nents such as scales and layers ». Sans ren­trer dans les détails de cet ouvrage, on peut résu­mer le prin­cipe de base qui est de sépa­rer les don­nées de la repré­sen­ta­tion gra­phique et de divi­ser la repré­sen­ta­tion en élé­ments de base tels que les courbes, les axes ou les labels. Ça peut sem­bler un peu confus au début mais cette façon de faire pré­sente de nom­breux avan­tages. Une fois les don­nées mises en forme, il ne sera plus néces­saire d’y reve­nir. Il est alors pos­sible de les repré­sen­ter sous forme de plot, de courbes, de bar­plot, et de bien d’autres façons en uti­li­sant juste le bon outil. Ren­trons main­te­nant un peu dans le détail.

Installation

L’installation des "packages" R est en géné­ral très simple. Ggplot2 ne fait pas excep­tion à la règle. Dans votre console R, tapez sim­ple­ment

install.packages('ggplot2')

et le package devrait s’installer tout seul. En cas de pro­blème je vous ren­voie à la doc de ggplot2.

Principes de base de ggplot2

Dans ggplot2, un "plot" se décom­pose de la manière sui­vante Plot <- data + Aes­the­tics + Geo­me­try Si le pre­mier terme n’est pas vrai­ment mys­té­rieux, les deux autres sont déjà un peu moins com­muns. Pour les don­nées, celles-ci doivent prendre une struc­ture par­ti­cu­lière mais nous y revien­drons un peu plus tard. Sous le terme "Aes­the­tics" on va retrou­ver tout ce qui concerne les cou­leurs, les tailles, les formes, les labels mais aus­si quelles don­nées doivent être consi­dé­rées en x et en y par exemple. "Geo­me­try" va regrou­per les options concer­nant les types de gra­phique (plot, his­to­gramme, heat­map, box­plot, etc…). Ces dif­fé­rents élé­ments vont être com­bi­nés dans un objet à par­tir duquel on va pou­voir faire les repré­sen­ta­tions dans une fenêtre gra­phique ou dans un fichier. Et lorsque l’on vou­dra chan­ger la cou­leur ou la forme ou le type de gra­phique il suf­fi­ra de modi­fier ce para­mètre dans l’objet sans avoir besoin de tou­cher aux autres puis de faire à nou­veau la repré­sen­ta­tion gra­phique. Ça peut paraître un peu confus au début mais quelques exemples vont vite éclair­cir le tout.

Avant toutes choses les données

Les don­nées sont bien sûr la base. La struc­ture des don­nées peut être un peu dérou­tante au début mais on s’y fait assez vite. Il faut mettre les don­nées dans une table de telle sorte qu’une des colonnes de la table contien­dra les don­nées sur x, une autre les don­nées sur y et encore une autre les dif­fé­rentes condi­tions. Pre­nons l’exemple d’une ciné­tique. On ima­gine qu’on a 13 points, un toutes les 5 minutes pen­dant 1 heure et qu’on com­pare 2 condi­tions pour une réac­tion enzy­ma­tique. Le résul­tat qu’on observe sera une den­si­té optique (D.O.) à 280nm. On aura la struc­ture sui­vante :

TimeAbsCond
00.1Without enzyme
50.09Without enzyme
100.12Without enzyme
150.13Without enzyme
200.11Without enzyme
250.07Without enzyme
300.09Without enzyme
350.1Without enzyme
400.11Without enzyme
450.11Without enzyme
500.13Without enzyme
550.1Without enzyme
600.07Without enzyme
00.08With enzyme
50.12With enzyme
100.18With enzyme
150.29With enzyme
200.46With enzyme
250.89With enzyme
301.12With enzyme
351.34With enzyme
401.45With enzyme
451.54With enzyme
501.59With enzyme
551.62With enzyme
601.61With enzyme

Cette struc­ture res­semble à ce qu'on peut trou­ver dans une table d'une base de don­nées. Il y a un peu de redon­dance d'information mais c'est très lisible. J’ai mis ce tableau dans un petit fichier que l'on va char­ger dans R.

data_kinetic_01 <- read.delim("data_kinetic_01.txt")

Premier "plot"

Com­men­çons par faire un plot simple, la DO en fonc­tion du temps avec des cou­leurs et des formes dif­fé­rentes pour les 2 échan­tillons.

p <- ggplot(data=data_kinetic_01, aes(x=Time, y=Abs, colour=Cond, shape=Cond))

Décryp­tons un peu cette ins­truc­tion. On créé un objet ggplot et on lui indique quelles don­nées il faut uti­li­ser (data=data_kinetic_01). Puis les para­mètres de "Aes­the­tics" sont défi­nis (aes(x=Time, y=Abs, colour=Cond, shape=Cond)). Dans cette com­mande, il est indi­qué d’utiliser la colonne Time pour x et la colonne Abs pour y. Pour les cou­leurs et les formes la colonne Cond sera uti­li­sée. Ce para­mètre peut être plus dif­fi­cile à com­prendre car dans la colonne Cond, il n'y a aucune indi­ca­tion de cou­leur ou de forme. En réa­li­té ggplot2 défi­nit lui même les cou­leurs et formes à uti­li­ser. La colonne Cond va ser­vir à indi­quer le groupe auquel chaque point appar­tient. On voit que dans notre cas, cette colonne contient 2 valeurs dis­tinctes "without enzyme" et "with enzyme". Ggplot2 va donc défi­nir 2 cou­leurs et 2 formes de points. La par­tie "geo­me­try" est ensuite ajou­tée par la com­mande ci-des­sous. Le but étant de des­si­ner des points, on va donc logi­que­ment uti­li­ser la com­mande geom_​poinet sim­ple­ment l'ajouter à l’objet qui vient d'être créé.

p <- p + geom_point(size=4)

Et voi­là notre objet est prêt. Il ne reste plus qu’à le repré­sen­ter dans une fenêtre gra­phique clas­sique.

print(p)

Ce qui donne le "plot" sui­vant :
kinetics_plot_01

Le plot cor­res­pond à ce qu’on attend. On voit bien les 2 séries de don­nées avec des formes et cou­leurs dif­fé­rentes. A par­tir de là, on peut agré­men­ter un peu le graph en ajou­tant un titre par exemple ou en reliant les points.

p <- p + ggtitle("My beautiful enzyme")
p <- p + geom_line(size=2)

kinetics_plot_02

Il est aus­si pos­sible d’ajouter une courbe lis­sée.

p <- ggplot(data=data_kinetic_01, aes(x=Time, y=Abs, colour=Cond, shape=Cond)) + geom_point(size=4) p <- p+ geom_smooth()

kinetics_plot_03

L'ajout d'éléments à la figure est très simple et de nom­breuses fonc­tions sont dis­po­nibles. Il fau­dra juste par­cou­rir la docu­men­ta­tion pour trou­ver celle qui convient mais les noms sont assez expli­cites et leur uti­li­sa­tion plu­tôt intui­tive. A par­tir des mêmes don­nées on peut par exemple repré­sen­ter les don­nées sous forme d’histogramme.

p <- ggplot(data=data_kinetic_01, aes(x=Time, y=Abs, fill=Cond)) + geom_histogram(stat='identity')

kinetics_plot_04

La valeur iden­ti­ty du para­mètre stat indique à la fonc­tion d’utiliser toutes les valeurs du tableau au lieu de faire un his­to­gramme de répar­ti­tion. Les barres sont empi­lées alors qu’on les vou­drait sépa­rées. Le para­mètre posi­tion avec la valeur dodge va sépa­rer les barres.

p <- ggplot(data=data_kinetic_01, aes(x=Time, y=Abs, fill=Cond)) + geom_histogram(stat='identity', position='dodge')

kinetics_plot_05

Et voi­là. Une fois la figure finie, il est pos­sible de l'exporter dans une image ou dans un fichier pdf est  à l'aide de la fonc­tion ggsave

ggsave(plot=p, file="kinetics_plot_01.png")

l'extension du fichier ser­vi­ra à indi­quer à ggsave le for­mat de fichier vou­lu.

Allons plus loin

Bon, certes c’est assez sym­pa mais mal­gré tout ça reste assez basique et les fonc­tions de base de R font tout aus­si bien presque aus­si faci­le­ment. On va donc faire des choses un peu plus com­pli­quées.

Histogrammes

Cette fois, les don­nées seront géné­rées de façon aléa­toires : 3 condi­tions (A, B ou C) et 100 mesures pour chaque.

nb.samples=100
df2 <- data.frame(id = rep(1:nb.samples, times=3), condition = factor( rep(c("A","B","C"), each=nb.samples)), value = c(rnorm(nb.samples),rnorm(nb.samples, mean=.5, sd=2), rnorm(nb.samples, mean=2.1, sd=0.5)))

Pour obser­ver la répar­ti­tion des valeurs, il suf­fit d'utiliser la fonc­tion geom_​histogramm

p <- ggplot(df, aes(x=value))
p <- p + geom_histogram(binwidth=.5, colour="black", fill="white")

histo_01

Il est pos­sible d'ajouter une ligne cor­res­pon­dant à la moyenne.

p <- p + geom_vline(aes(xintercept=mean(value, na.rm=T)), color="red", linetype="dashed", size=1)

histo_02

On passe à un fond blanc pour faci­li­ter une éven­tuelle impres­sion.

p <- p + theme_bw()

histo_03

Ima­gi­nons main­te­nant que l'on sou­haite obser­ver la répar­ti­tions des valeurs pour chaque condi­tion sépa­rée.

p <- ggplot(df, aes(x=value, fill=condition))
p <- p + geom_histogram(binwidth=.5, colour="black")
p <- p + theme_bw()

histo_04

Cette repré­sen­ta­tion n’est pas idéale. Pours sépa­rer les valeurs dans des plots dif­fé­rents, il va fal­loir uti­li­ser une nou­velle fonc­tion facet_​grid. Les plots peuvent être dis­po­sés hori­zon­ta­le­ment.

p <- p + facet_grid( . ~ condition)

histo_05

ou ver­ti­ca­le­ment.

p <- p + facet_grid( condition ~ .)

histo_06

Un peu de déco­ra­tion.

p <- p + ggtitle("yet another ggplot2 histogram")
p <- p + xlab(label="my favorite measurement")

histo_07

Pour com­ple­ter la figure avec quelques infor­ma­tions sur les dis­tri­bu­tions il suf­fit d'utiliser le package plyr, créé par le même déve­lop­peur. Je ne rentre pas dans le détail de plyr, je le décri­rai dans un autre article.

library(plyr)

A l’aide de plyr on cal­cule les moyennes par condi­tion.

df.stats <- ddply(df, "condition", summarise, value.mean=mean(value), value.sd=sd(value))

On ajoute des lignes ver­ti­cales au niveau des moyennes cal­cu­lées.

p <- p + geom_vline(data=df.stats, aes(xintercept=value.mean), linetype="longdash", size=1, colour="black")

histo_08

Puis on trace les lignes cor­res­pon­dant aux limites à plus ou moins 3 écart-types de la moyenne.

p <- p + geom_vline(data=df.stats, aes(xintercept=value.mean - 3*value.sd), linetype="dotted", size=1, colour="black")
p <- p + geom_vline(data=df.stats, aes(xintercept=value.mean + 3*value.sd), linetype="dotted", size=1, colour="black")

histo_09

Boxplots

A par­tir des même don­nées on peut aus­si des­si­ner des "box­plots".

p <- ggplot(data=df, aes(x=condition, y=value)) p <- p + geom_boxplot()

La fonc­tion fait ce qu'on a attend d'elle, des "box­plots" basiques

box_plot_01

Ajou­tons les points

p <- p + geom_point()

box_plot_02

Comme le graphe manque un peu de lisi­bi­li­té, on colore les "box­plots" en fonc­tion des condi­tions et on dis­perse les points sur toute la lar­geur.

p <- ggplot(data=df, aes(x=condition, y=value, fill=condition))
p <- p + geom_boxplot()
p <- p + geom_jitter(position = position_jitter(width = .2))

box_plot_03

On peut, si on le sou­haite, relier les points entre eux. Ils seront reliés par leur rang dans le tableau

p <- ggplot(data=df, aes(x=condition, y=value, fill=condition))
p <- p + geom_boxplot()
p <- p + geom_point(aes(shape=condition), size=3)
p <- p + geom_line(aes(group=id), linetype='dashed')

box_plot_04

Pour per­son­na­li­ser un peu plus le graph avec un fond blanc et en éli­mi­nant la légende des abs­cisses, il fau­dra uti­li­ser la fonc­tion theme

my.theme <- theme_bw()+ theme(axis.text=element_text(size=16), axis.title.x=element_blank())
p <- p + my.theme

box_plot_05

Scatterplots

Un der­nier exemple avec cette fois des "scat­ter­plots". On uti­li­se­ra la fonc­tion mvr­norm du package MASS pour géné­rer les don­nées

library(MASS)
set.seed(123)
nb.samples <- 25
correlation.group.1 <- 0.65
m.data.group.1 <- mvrnorm(nb.samples, mu = c(10,5), Sigma = matrix(c(1,correlation.group.1,correlation.group.1,1), ncol = 2), empirical = TRUE)
correlation.group.2 <- 0.85
m.data.group.2 <- mvrnorm(nb.samples, mu = c(15,6), Sigma = matrix(c(1,correlation.group.2,correlation.group.2,1), ncol = 2), empirical = TRUE)
df <- data.frame(id = rep(1:nb.samples, times=2), condition = factor( rep(c("A","B"), each=nb.samples)), protein.1 = c(m.data.group.1[,1],m.data.group.2[,1]), protein.2 = c(m.data.group.1[,2],m.data.group.2[,2]))

Repré­sen­tons dans un pre­mier temps les points.

p <- ggplot(data=df, aes(x=protein.1, y=protein.2))
p <- p + geom_point(size=4)

scatterplot_01

Puis ajou­tons une courbe de régres­sion.

p <- p + stat_smooth()

scatterplot_02

La fonc­tion stat_​smooth per­met d'obtenir la courbe pas­sant au plus près de l'ensemble des points. Cepen­dant, on ne tient pas compte des dif­fé­rentes condi­tions. Pour les sépa­rer, il faut uti­li­ser l'argument colour.

p <- ggplot(data=df, aes(x=protein.1, y=protein.2, colour=condition, shape=condition))
p <- p + geom_point(size=4)

scatterplot_03

On choi­si d'ajouter une droite de régres­sion et non plus une courbe lis­sée en uti­li­sant la méthode lm en para­mètre à la fonc­tion stat_​smooth

p <- p + stat_smooth(method = "lm")

scatterplot_04

On rajoute un peu de déco­ra­tion, c'est tou­jours mieux

p <- p + theme_bw() p <- p + ggtitle("yet another ggplot2 scatterplot")

scatterplot_05

Et on obtient nos points avec leur courbe de ten­dance res­pec­tives. Elles sont sur le même graphe mais il est très facile de les sépa­rer.

p <- p + facet_grid(. ~ condition)

scatterplot_06

Les 2 "plots" ont les mêmes échelles. Ce com­por­te­ment est sou­vent inté­res­sant mais dans notre cas, cela nuit un peu à la lisi­bi­li­té. On éli­mine la contrainte d’échelle sur x.

p <- p + facet_grid(. ~ condition,scales="free_x")

scatterplot_07

Et voi­là on a 2 jolis graphes indé­pen­dants.

Pour aller plus loin

J’ai pré­sen­té quelques fonc­tions basiques de ggplot2. Le package per­met beau­coup plus de choses et je n’ai pas encore tout explo­ré. Il existe pas mal de res­sources pour aller plus loin.

Le mieux étant de le décou­vrir petit à petit avec de vraies don­nées. Mer­ci aux relec­teurs Maxi_​zu, Estel et Bu pour leur cor­rec­tions et leurs conseils avi­sés et sur­tout à Vincent Rouilly qui m’a fait décou­vrir ggplot2 et qui sur­tout a ima­gi­né une bonne par­tie des exemples pré­sen­tés ici.

Vous avez aimé ? Dites-le nous !

Moyenne : 0 /​ 5. Nb de votes : 0

Pas encore de vote pour cet article.

Partagez cet article :



Pour continuer la lecture :


Commentaires

15 réponses à “Guide de démarrage pour ggplot2, un package graphique pour R”

  1. Avatar de Fluîd

    Je connais­sais déjà ce package mais n'en mesu­rais pas autant les pos­si­bi­li­tés.
    Mer­ci beau­coup pour ce guilde très ins­truc­tif !

  2. Avatar de Evelyne Duvernois-Berthet
    Evelyne Duvernois-Berthet

    Hal­le­lu­jah !!
    Moi qui galère tou­jours avec ggplot2, j'ai même plus d'excuses…

  3. Avatar de Christel Dartigues-Pallez
    Christel Dartigues-Pallez

    Mer­ci pour cet superbe tuto­riel.
    J'ai juste une ques­tion : j'affiche une matrice de confu­sion à l'aide de ggplot, et je sou­hai­te­rait l'afficher dans l'autre sens (un axe à gauche et l'autre en haut) afin que la dia­go­nale de ma matrice n'aille pas du coin bas gauche vers le coin haut droit mais du coin en haut à gauche vers le coin en bas à droite. Savez-vous si cela est pos­sible ?

    Mer­ci encore pour votre tra­vail très inté­res­sant et sur­tout extrê­me­ment utile.

    1. Avatar de waqueteu
      waqueteu

      Alors ce n'est pas très simple à faire. Mais je pense avoir trou­ver une solu­tion.
      Il faut voir si ca s'applique dans ce cas.
      J'ai une matrice de confu­sion (com­Mat) très simple

            -1 1
        -1  2 1
        1   1 3
      
      je fais les choses suivantes :
      
      confMat.dataframe = as.data.frame(confMat)
      
      la j'ai une datframe avec 3 colonnes, les 2 premières sont les facteurs qui seront utiliser pour les labels des axes et la 3eme est l'intensité ou la fréquence.
      
        Var1 Var2 Freq
      1   -1   -1    2
      2    1   -1    1
      3   -1    1    1
      4    1    1    3
      
      les axes dans ggplot, quand on représente des données étant des facteurs, sont orienté selon l'ordre des facteurs.
      ici pour Var2 j'aurais :
      
      [1] -1 -1 1  1 
      Levels: -1 1
      
      Voyez l'ordre des facteurs => Levels: -1 1
      
      si on veut un axe inversé il faut inversé l'ordre des facteurs.
      
      Je propose cette solution, moche mais qui marche :
      
      confMat.dataframe$Var2=factor(as.character(confMat.dataframe$Var2), levels=sort(unique(confMat.dataframe$Var2), decreasing = T))
      
      en gros j'extrait les facteurs, j'en fait un vecteur de character simples, puis je le retransforme en facteurs en imposant l'ordre des facteurs. et pour cela j'utilise unique pour obtenir les facteurs et sort pour les ordonner (avec decreasing=T pour que 1 soit avant -1.
      
      j'obtiens alors pour Var2 
      
      [1] -1 -1 1  1 
      Levels: 1 -1
      
      notez que l'ordre des valeurs reste inchangé mais que l'ordre des facteurs est inversé.
      
      et voila, c'est fait.
      
      Var2 sera bien sur dans votre cas la varaible a représenter sur l'axe y.
  4. ça donne envie de faire de beaux graphes avec ggplot2 mer­ci !

  5. Avatar de Leo GARCIA
    Leo GARCIA

    Bon­jour,
    Mer­ci pour ce tuto­riel, très inté­res­sant et qui per­met de com­prendre beau­coup de choses quand on com­mence avec ggplot…

    Cepen­dant, j'ai une ques­tion qui n'est tou­jours pas réso­lue (je ne sais pas si le "lieu" est appro­prié, je tente tout de même…)

    J'aimerais réa­li­ser un graph iden­tique à celui-ci
    http://​s24​.postimg​.org/​f​v​w​t​7​4​2​t​1​/​s​u​l​t​a​n​2​0​1​3​.​png

    qui repré­sente en x, des varia­tions de T°, en y des varia­tions de pluie…les points étant clas­sés selon leur "coor­don­nées" pluie et tem­pe­ra­ture, et dans des cases cor­res­pon­dant à la varia­tion de ren­de­ment (qté de céréale pro­duite par hec­tare) que pro­voque la varia­tion pluie/​température…

    ce que je ne par­viens pas à réa­li­ser c'est cette colo­ra­tion rouge/​bleu des rec­tangles, pour les dif­fé­rentes classes de varia­tion de ren­de­ment.

    Je pense que mon tableau doit conte­nir les classes de varia­tion de tem­pé­ra­ture, pluie et ren­de­ment mais je n'ai pas idée du code pour repré­sen­ter tout cela…

    En espé­rant que vous pour­rez m'aider,

    Mer­ci d'avance,

    Léo

    1. Salut Léo,

      je ne suis pas sûre à 100% d'avoir com­pris ta ques­tion mais pour repro­duire les rec­tangles et le gra­dient de cou­leur je pense qu'il faut que tu regardes du côté de "geom_​tile":

      http://​docs​.ggplot2​.org/​c​u​r​r​e​n​t​/​g​e​o​m​_​t​i​l​e​.​h​tml

      1. Avatar de Leo GARCIA
        Leo GARCIA

        Salut,

        Je vais regar­der de ce côté là, je te dirai si ça a fonc­tion­né !

        mer­ci pour la réponse,

        Léo

  6. Bon­jour et mer­ci pour ce tuto !
    A la base j'avais une ques­tion, mais en com­men­cant à écrire ce com­men­taire j'ai trou­vé ma réponse.
    De quoi me don­ner envie de conti­nuer à apprendre à me ser­vir de ggplot.
    Yoann

  7. Avatar de marine petit
    marine petit

    Bon­jour,

    mer­ci beau­coup pour le tuto­riel c'est très utile. une petite cor­rec­tion :
    Il manque l'argument data= pour la fonc­tion geom_​vline

    "Il est pos­sible d'ajouter une ligne cor­res­pon­dant à la moyenne.

    p <- p + geom_vline(aes(xintercept=mean(value, na.rm=T)), color="red", linetype="dashed", size=1)"

  8. Bon­jour,

    Je cherche à faire un gra­phique de plu­sieurs ciné­tiques. Dans mon fichier Data, ma pre­mière colonne est Time..h. (le temps en heure), les autres colonnes cor­res­pondent aux mesures de ciné­tique pour 6 échan­tillons dont des dupli­cats.

    Ça res­semble à ça :
    Time..h. | SampleX1.1 | SampleX1.2 | SampleX2.1 | SampleX2.2 .……

    SampleX1.1 et SampleX1.2 sont des dupli­cats.

    Voi­là ce qui fonc­tionne pour l'instant :
    Time = Data$Time..h.
    Sample1= Data$Sample.X1.1
    g <- ggplot(Data, aes(x=Time, y=Sample1)) + geom_​smooth() # set se=FALSE to tur­noff confi­dence bands
    plot(g)

    Mais j'aimerais com­bi­ner les mesures des dupli­cats pour éta­blir l'étendue des mesures à chaque échantillons/​duplicats et à tous les cycles de mesure.

    Je ne sais pas si c'est très clair x)
    Mer­ci d'avance !!!

    1. Bon­jour Claire,

      Il faut en fait dans un pre­mier temps pas­ser vos don­nées dans ce qu'on appelle le for­mat long (https://statistique-et-logiciel‑r.com/wide-et-long/).

      Pour la suite, j'ai repro­duis des don­nées aléa­toire en espé­rant qu'elle soient de même for­mat que ce que vous avez. Voi­ci un petit code qui devait vous conve­nir :

      [crayon-6699cb5137051161738111/]

      1. Je n'avais pas vu la pré­ci­sion de com­bi­nai­son des dupli­cat. Une petit mise à jour 😉

        [crayon-6699cb513506a359752575/]

  9. […] Si vous faites par­tis des rares uti­li­sa­teurs de R qui n’utilisent pas encore ggplot2, vous pour­rez trou­ver deux intro­duc­tions à ce package, en fran­çais, ici et là. […]

Laisser un commentaire