GGplot - boxplot : ajout moyenne par groupe/moyenne générale

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

GGplot - boxplot : ajout moyenne par groupe/moyenne générale

Messagepar Bigot Anthony » 12 Juil 2013, 16:54

Bonjour,

je fais des boites à moustache par groupe et j'aimerais ajouter sur chaque panneau :
- la moyenne du groupe
- la moyenne général

Code : Tout sélectionner

# données test
test<-data.frame(classe=c(rep(1:3, 9)), ind=rep(1:9, 3), values=rnorm(n=27, 0, 1))
# aperçu
test[with(test, order(classe, ind)),]
   # classe ind       values
# 1       1   1 -0.982562538
# 10      1   1  0.671096635
# 19      1   1 -2.144761133
# 4       1   4  1.042936218
# 13      1   4  0.019593993
# 22      1   4  1.636128502
# 7       1   7  0.172440543
# 16      1   7  1.377762072
# 25      1   7  1.226224218
# 2       2   2  0.857910359
# 11      2   2  0.923269540
# 20      2   2  0.268502722
# 5       2   5 -0.372159562
# 14      2   5  0.367394526
# 23      2   5  1.801222973
# 8       2   8 -1.573680102
# 17      2   8  0.169825303
# 26      2   8 -0.008336949
# 3       3   3  0.591973841
# 12      3   3  0.569334749
# 21      3   3  0.272558998
# 6       3   6  0.233889287
# 15      3   6  1.390091984
# 24      3   6  1.466123905
# 9       3   9  1.054160179
# 18      3   9  0.525190927
# 27      3   9 -0.109793719

# boxplot par groupe
ggplot(test, aes(factor(ind), values, fill=factor(classe), group=ind)) + geom_boxplot() + facet_grid(. ~ classe, scales="free_x")


J'ai essayé avec

Code : Tout sélectionner

+  stat_summary(fun.y=mean ,geom="line",color="red", mapping=aes(group=1))


mais j'ai un warning comme quoi il n'y a qu'un élément par groupe ; en remplaçant "line" par "point" j'obtiens la moyenne de chaque "ind" représentée par un point...

j'ai également essayer stat_smooth sans succès.

est-ce qu'il faut passer par un nouveau layer? ou est-ce que c'est faisable comme ça?

Merci
La règle des 3G vous connaissez? R est:
GRATUIT GIGANTESQUE et GENIAL

Renaud Lancelot
Messages : 2484
Enregistré le : 16 Déc 2004, 08:01
Contact :

Messagepar Renaud Lancelot » 12 Juil 2013, 17:04

Si ça t'intéresse je peux te proposer une solution lattice.
Renaud

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

Messagepar Bigot Anthony » 12 Juil 2013, 17:09

J'ai la solution boxplot classique aussi, mais pour tout homogénéiser dans mes rapports, publis je préférerais continuer avec GGplot...

Mais tu peux poster, ça pourrait en interesser d'autres... (spécifie juste le Sujet du post en indiquant Lattice du coup)

Merci pour ta réponse rapide Renaud.
La règle des 3G vous connaissez? R est:

GRATUIT GIGANTESQUE et GENIAL

Stéphane Laurent
Messages : 1557
Enregistré le : 05 Déc 2006, 19:07

Messagepar Stéphane Laurent » 12 Juil 2013, 17:13

Dans le aes() il faut obligatoirement x et y :

Code : Tout sélectionner

?stat_summary
...
Aesthetics:

     ‘stat_summary’ understands the following aesthetics (required
     aesthetics are in bold):

        • ‘*x*’

        • ‘*y*’

donc j'essayerais ça :

Code : Tout sélectionner

aes(x=ind, y=values)

(avec ind en facteur)

Renaud Lancelot
Messages : 2484
Enregistré le : 16 Déc 2004, 08:01
Contact :

Messagepar Renaud Lancelot » 12 Juil 2013, 18:05

Avec lattice et grid (voir latticeExtra pour des thèmes "ggplot-like")

Code : Tout sélectionner

library(lattice)
library(grid)

bwplot(values ~ ind | factor(classe), data = test, subscripts = TRUE,
       horizontal = FALSE, between = list(x = 1/2),
       panel = function(x, y,...){
         panel.grid()
         panel.bwplot(x, y,...)
         m <- format(round(mean(y), 2), nsmall = 2)
         M <- format(round(mean(test$values), 2), nsmall = 2)
         grid.text(label = bquote(bar(italic(m))[g] == .(m)),
                   x = unit(1, "npc"), y = unit(1, "npc"),
                   hjust = 1.1, vjust = 1.1, gp = gpar(cex = .8))
         grid.text(label = bquote(bar(italic(m))[a] == .(M)),
                   x = unit(1, "npc"), y = unit(1, "npc") - unit(1.25, "line"),
                   hjust = 1.1, vjust = 1.1, gp = gpar(cex = .8))
       })
Renaud

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

Messagepar Bigot Anthony » 12 Juil 2013, 23:03

@Renaud
Merci, cela aidera les fans de lattice ; cependant j'obtiens toujours la moyenne de chaque individu représenté comme un point au milieu de la boite à moustache.

@Stéphane
J'ai essayé mais je n'obtiens pas le résultat escompté ; les panneau doublent de largeur (come si stat_summary ajoutait doublait les individus de chaque groupe) mais rien n'apparait à part des emplacements vides...

je vais regarder de plus pret au niveau aes.
La règle des 3G vous connaissez? R est:

GRATUIT GIGANTESQUE et GENIAL

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

Messagepar Bigot Anthony » 12 Juil 2013, 23:16

Rappel code initial

Code : Tout sélectionner

ggplot(test, aes(factor(ind), values, fill=factor(classe), group=ind)) + geom_boxplot() + facet_grid(. ~ classe, scales="free_x")


En ajoutant :

Code : Tout sélectionner

+  stat_summary(fun.y=mean ,geom="point",color="red", aes(x=classe, y=mean(values)))

j'obtiens la moyenne générale sur chaque panneau sous forme d'un point ; par contre avec "ligne", toujours rien ;
Et avec :

Code : Tout sélectionner

+  stat_summary(fun.y=mean ,geom="point",color="red", aes(x=ind, y=mean(values)))

on obtient la moyenne générale représentée pour chaque individu sous forme de point ... toujours pas terrible.


Reste à trouver comment le faire avec une droite et comment mettre la moyenne de chaque groupe...


Je regarde demain du coté de

Code : Tout sélectionner

library(doBy)
a<-summaryBy(values ~ ind + class , test, FUN=c(mean))

puis utilisé dans un layer ou avec un fonction de traçage.
La règle des 3G vous connaissez? R est:

GRATUIT GIGANTESQUE et GENIAL

Renaud Lancelot
Messages : 2484
Enregistré le : 16 Déc 2004, 08:01
Contact :

Messagepar Renaud Lancelot » 13 Juil 2013, 07:59

Bigot Anthony a écrit :@Renaud
Merci, cela aidera les fans de lattice ; cependant j'obtiens toujours la moyenne de chaque individu représenté comme un point au milieu de la boite à moustache.

@Stéphane
J'ai essayé mais je n'obtiens pas le résultat escompté ; les panneau doublent de largeur (come si stat_summary ajoutait doublait les individus de chaque groupe) mais rien n'apparait à part des emplacements vides...

je vais regarder de plus pret au niveau aes.


Désolé, mais ta demande n'est pas claire. Quand tu écris:

je fais des boites à moustache par groupe et j'aimerais ajouter sur chaque panneau :
- la moyenne du groupe
- la moyenne général


je comprends alors que tu veux annoter chaque panel avec la moyenne du groupe et la moyenne générale. C'est exactement ce que fait le code que j'ai posté.

En revanche, le point que tu vois sur les boxplots par individu n'est pas la moyenne, mais la médiane (voir l'aide de boxplot.stats).

Que veux-tu faire exactement: annoter les graphes, ou changer la fonction pour faire apparaître dans la boite à moustache la moyenne (au lieu de la médiane) et la moyenne générale ?

La 2e solution est probablement une très mauvaise idée car tu changes l'idée de base du boxplot qui est de faire une représentation graphique de la distribution basée sur les quantiles (et non la moyenne).

Si tu veux rester dans la représentation graphique sans annotation écrite, utilise l'équivalent abline dans lattice / ggplot2.

Code : Tout sélectionner

bwplot(values ~ ind | factor(classe), data = test, subscripts = TRUE,
       horizontal = FALSE, between = list(x = 1/2),
       key = list(corner = c(0,1), y = .94,
                  text = list(c("Group mean", "Overall mean")),
                  lines = list(lty = c("dotted", "dashed"))),
       panel = function(x, y,...){
         panel.grid()
         panel.bwplot(x, y,...)
         m <- mean(y)
         M <- mean(test$values)
         panel.abline(h = m, lty = "dotted")
         panel.abline(h = M, lty = "dashed")
       })
Renaud

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

Messagepar Bigot Anthony » 13 Juil 2013, 08:24

En effet ce n'est pas très clair.

Je veux garder les boxplots tels quels.
L'idée est d'ajouter des droites pour avoir une idée de comment se situe chaque groupe par rapport à l'ensemble parce que les boxplots dans mon cas réel ne suffisent pas à bien différencier certains groupes.

L'idée est donc d'ajouter une droite (en pointillés par exemple) qui représente la moyenne général sur l'ensemble du graphique ; possible avec le code suivant que je viens de trouver :

Code : Tout sélectionner

+   geom_line(aes(x =factor(ind), y = mean(values), group=classe), colour = "red" ,linetype="dashed", size = 1)

Le "group=classe" changé en "group=ind" ne modifie rien et sur chaque panneau, la moyenne est limitée par les moustaches des boites les plus externes ; ce serait plus sympa d'avoir une unique droite qu itraverse les 3 paneaux.


La seconde idée est de tracer la moyenne par groupe sur chaque panneau (en trait plein par exemple) ; de cette manière on verra les groupes qui ont une moyenne supérieure/inférieure à la moyenne général.


J'ai regardé du coté de geom_abline() mais sans succès.

_________
EDIT : geom_hline()
_________
Pour la moyenne général tout individus confondus qu itraversent l'ensemble des panneaux :

Code : Tout sélectionner

+   geom_hline(aes(x =factor(ind), y = mean(values), group=classe), colour = "red" ,linetype="dashed", size = 1)
La règle des 3G vous connaissez? R est:

GRATUIT GIGANTESQUE et GENIAL

Bigot Anthony
Messages : 108
Enregistré le : 07 Avr 2009, 09:07

[RESOLU] Ajout moyenne général / moyenne groupe sur boxplot

Messagepar Bigot Anthony » 13 Juil 2013, 09:08

Création des moyennes par groupe pour la suite :

Code : Tout sélectionner

a<-summaryBy(values ~ classe , test, FUN=c(mean))


Boxplot par groupe :

Code : Tout sélectionner

ggplot(test, aes(factor(ind), values, fill=factor(classe), group=ind)) + geom_boxplot() + facet_grid(. ~ classe, scales="free_x") +


Ajout de la moyenne générale sur les panneau (en rouge pointillé ici):

Code : Tout sélectionner

 geom_abline(aes(intercept = mean(values), slope = 0), colour = "red" ,linetype="dashed", size = 1) +


Ajout des moyennes par groupe sur les panneaux correspondant (utilisation des moyennes par groupe du data.frame "a") :

Code : Tout sélectionner

 geom_abline(data=a, aes(intercept = values.mean, slope = 0, group=classe), colour = "blue", size = 1)


En effet la solution venait du "abline" de GGplot ; il fallait juste trouver quoi y mettre :)

Merci pour votre aide Renaud et Stéphane.
La règle des 3G vous connaissez? R est:

GRATUIT GIGANTESQUE et GENIAL

Leo GARCIA
Messages : 9
Enregistré le : 27 Juil 2015, 13:40

Re: GGplot - boxplot : ajout moyenne par groupe/moyenne générale

Messagepar Leo GARCIA » 28 Juil 2015, 16:55

Bonjour,

Je viens relancer ce vieux post avec une nouvelle question, un peu similaire. Je reprends le même genre d'exemple, un peu modifié :

Code : Tout sélectionner

# données test
test<-data.frame(classe=c(rep(1:4, 6)), ind=rep(1:3, 8), values=rnorm(n=24, 0, 1))
# aperçu
test[with(test, order(classe, ind)),]

   classe ind      values
1       1   1 -0.28067207
13      1   1 -0.46222657
5       1   2 -1.01108050
17      1   2  0.55695085
9       1   3  0.35416016
21      1   3 -0.26668396
10      2   1  0.39963688
22      2   1 -0.08072801
2       2   2 -3.09193281
14      2   2  0.66549723
6       2   3  0.31373540
18      2   3  0.29443292
7       3   1 -0.30449699
19      3   1 -0.33010727
11      3   2  0.54070960
23      3   2  1.55157691
3       3   3  2.07797334
15      3   3 -0.04044626
4       4   1  0.44297708
16      4   1  1.03221155
8       4   2  1.06340044
20      4   2  0.12170260
12      4   3  0.38842933
24      4   3 -0.16988527

# boxplot par groupe
ggplot(test, aes(x=as.factor(ind),y=values, fill=as.factor(classe))) + geom_boxplot()


J'aimerai ajouter la moyenne sur chaque boxplot, or je n'ai pas "trié" les boxplot les uns des autres avec "group" mais avec "fill", et les exemples ci-dessus ne fonctionnent pas...

Quelqu'un aurait-il la solution ?

Merci !

Léo


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité