Comment utiliser ggplot dans une boucle ou dans une fonction ?

ggplot_aes_string()

ggplot() est la fonction de base du package ggplot2, qui est le package incontournable pour réaliser des représentations graphiques avec R. ggplot2 est extrêmement populaire car il permet de réaliser une multitude de visualisations, de façon rapide et esthétique.

La réalisation de plots avec ce package nécessite un petit apprentissage pour en comprendre le principe, mais ne pose pas de problème particulier, en pratique courante.

En revanche, lorsqu’on souhaite utiliser la fonction ggplot au sein d’une boucle, pour réaliser un graphique de façon itérative par exemple, ou encore lorsqu’on souhaite l’intégrer au sein d’une autre fonction, cela est généralement plus délicat.

La solution est en réalité très simple puisqu’elle consiste à utiliser l’argument aes_string à la place de l’argument aes lorsqu’on fait appel à la fonction ggplot!

Dans ce post, je vais donc vous montrer concrètement comment utiliser la fonction ggplot à l’intérieur d’une boucle for, puis au sein d’une fonction.

Si vous faites partis des rares utilisateurs de R qui n’utilisent pas encore ggplot2, vous pourrez trouver deux introductions à ce package, en français, ici et 

Table des matières

Définition du problème

Utilisation courante de ggplot2

Imaginons que je souhaite évaluer la linéarité de la relation entre deux variables. Pour cela, je peux réaliser un scatterplot avec ggplot2 et ajouter une droite de régression linéaire, ainsi qu’une courbe loess, par exemple. Comme cela :

ggplot_aes_string()

Pour réaliser ce plot, j’ai utilisé les données iris, restreintes à l’espèce “setosa”. Je les ai obtenues avec les commandes suivantes :

 setosa <- iris %>%
        dplyr::filter(Species=="setosa") %>%
        select(-Species) 

Le jeu de données “setosa” comporte quatre variables :

 head(setosa)

    ##   Sepal.Length Sepal.Width Petal.Length Petal.Width
    ## 1          5.1         3.5          1.4         0.2
    ## 2          4.9         3.0          1.4         0.2
    ## 3          4.7         3.2          1.3         0.2
    ## 4          4.6         3.1          1.5         0.2
    ## 5          5.0         3.6          1.4         0.2
    ## 6          5.4         3.9          1.7         0.4 

J’ai ensuite construit le scatter plot de la variable “Sepal.Length” en fonction de la variable “Sepal.Width”. La fonction ggplot permettant alors de définir :

  • le data.frame (tableau de données) qui contient les données, à
    l’aide de l’argument data
  • les variables à représenter à l’aide de l’argument :
    aes(y=Sepal.Length,x=Sepal.Width)

Le type “scatterplot” est ensuite défini à l’aide de la fonction geom_point. Et les fonctions geom_smooth permettent de tracer la courbe loess, puis la droite de régression. Au final les commandes sont les suivantes :

ggplot(setosa, aes(y=Sepal.Length,x=Sepal.Width)) +
        geom_point() +
        geom_smooth(method=loess, se=FALSE) +
        geom_smooth(method=lm, colour="red", fill="red", alpha=0.25) 

Utilisation automatisée de ggplot2

Imaginons à présent que je souhaite créer, de façon automatisée, un scatter plot de la variable “Sepal.Length”, en fonction de chacune des trois autres variables du jeu de données. Autrement dit, trois scatterplots, avec chacun une variable prédictive différente “Sepal.Width”, “Petal.Length” et “Petal. Width”.

Je pourrais biensur passer le jeu de données en format “long” à l’aide de la fonction gather.

setosa_long <- setosa %>%
        gather(variable,  value, -Sepal.Length)

    head(setosa_long)

    ##   Sepal.Length    variable value
    ## 1          5.1 Sepal.Width   3.5
    ## 2          4.9 Sepal.Width   3.0
    ## 3          4.7 Sepal.Width   3.2
    ## 4          4.6 Sepal.Width   3.1
    ## 5          5.0 Sepal.Width   3.6
    ## 6          5.4 Sepal.Width   3.9 

Puis utiliser la fonction facet_wrap.

 ggplot(setosa_long, aes(y=Sepal.Length, x=value))+

        geom_point() +
        geom_smooth(method=loess, se=FALSE) +
        geom_smooth(method=lm, colour="red", fill="red", alpha=0.25)+
        facet_wrap(~variable, scales="free") 
ggplot_aes_string()

Cette solution peut être adaptée lorsque le nombre de variables explicatives (celles que l’on va représenter sur l’axe des x) est faible. En revanche lorsque ce nombre est important cette solution conduit à des plots de petite taille et donc à une lisibilité réduite.

Imaginons donc que je souhaite créer ces 3 plots de façon distincte.
Deux solutions sont alors possibles :

  • utiliser directement la fonction ggplot dans une boucle
  • construire une fonction qui emploie la fonction ggplot, et
    l’intégrer dans une boucle.

Je vais donc vous montrer comment réaliser concrètement ces deux solutions.

Utiliser ggplot dans une boucle (for par exemple)

Le problème ici, dans la boucle, c’est de parvenir à changer itérativement la variable explicative (celle qui est représentée sur l’axe des x). Pour cela, on doit impérativement utiliser l’argument
aes_string car contrairement à l’argumentaes, il peut intégrer des chaines de caractères
. Les variables explicatives sont alors fournies à l’argument aes_stringen utilisant la fonction
colnames(data.frame)[i].

for(i in 2:ncol(setosa)) # on commence à 2 car la première variable est la variable réponse
    {  
        
        p <- ggplot(setosa) + 
            geom_point(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]))+
            geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=loess, se=FALSE)+
            geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=lm, colour="red", fill="red", alpha=0.25) +
            theme_classic ()
        print(p)
        
    } 
ggplot_aes_string()
ggplot_aes_string()
ggplot_aes_string()

Et si vous voulez sauvegarder automatiquement ces plots, vous pouvez utiliser les commandes suivantes :

for(i in 2:ncol(setosa))
    {  
            jpeg(paste(i, "jpeg", sep = "."), width = 15, height =12, units="cm", quality=75, res=300)
        
        p <- ggplot(setosa) + 
            geom_point(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]))+
            geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=loess, se=FALSE)+
            geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=lm, colour="red", fill="red", alpha=0.25) +
            theme_classic ()
        print(p)
        
        dev.off()
    } 

Utiliser ggplot dans une fonction

Une autre façon de faire, pour créer ces 3 plots, peut consister à créer une fonction plot, en utilisant ici encore l’argument aes_string

    my_plot <- function (df, x, y)
    {
      ggplot(df, aes_string(x=x, y=y))+
            geom_point()+
            geom_smooth( method=loess, se=FALSE)+
            geom_smooth(method=lm, colour="red", fill="red", alpha=0.25) +
            theme_classic ()
           
    } 

Qui s’utilise comme ceci :

my_plot(setosa, "Sepal.Width", "Sepal.Length") 
ggplot_aes_string()

Ensuite, cette fonction peut être intégrée dans une boucle for, comme cela par exemple :

 for(i in 2:ncol(setosa)){
      
      p <- my_plot(setosa, names(setosa)[i], "Sepal.Length")
      print(p)
    } 
ggplot_aes_string()
ggplot_aes_string()
ggplot_aes_string()

Et là encore, pour sauvegarder les plots automatiquement dans des fichiers jpeg, vous utiliser les lignes suivantes:

for(i in 2:ncol(setosa)){

      
        jpeg(paste(names(setosa)[i], "jpeg", sep = "."), width = 15, height =12, units="cm", quality=75, res=300)
      p <- my_plot(setosa, names(setosa)[i], "Sepal.Length")
      print(p)

      dev.off()
      } 

Voilà ! J’espère que cet article vous évitera de perdre inutilement du temps à la recherche d’une solution, et qu’il vous permettra de réaliser plus facilement vos plots de façon automatisée avec ggplot2.

Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee 🙏

Crédits photos : jambulboy

Poursuivez votre lecture

7 réponses

  1. Bonjour,

    Merci pour ce super sujet.

    Je n’arrive pas à afficher plusieurs graphiques en même temps avec aes-string. Est-ce qu’il y a des packages à installer pour que plusieurs graphiques s’affichent sur la même fenêtre ?

    Par exemple pour la commande :

    for(i in 2:ncol(setosa))
    {

    p <- ggplot(setosa)
    geom_point(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]))
    geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=loess, se=FALSE)
    geom_smooth(aes_string(y = "Sepal.Length", x = colnames(setosa)[i]),method=lm, colour="red", fill="red", alpha=0.25)
    theme_classic ()
    print(p)

    }

    J'obtient ce message :

    Warning messages:
    1: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, :
    pseudoinverse used at 0.0975
    2: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, :
    neighborhood radius 0.2025
    3: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, :
    reciprocal condition number 2.8298e-016
    4: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, :
    There are other near singularities as well. 0.01

    Seul le deuxième graphique s'affiche. Merci d'avance pour l'aide. Et merci aussi pour tous les autres articles 🙂

    1. Bonsoir Marc,

      non il n’est pas nécessaire d’installer d’autres packages. Normalement vous devriez retrouver les 3 plots réalisés successivement dans la fenêtre des plots. Pour comprendre ce qui se passe vous pouvez initialiser i à 2 puis copier les coller les lignes de commandes dans la console, puis passer i à 3 et recommencer, etc… Les warnings concernent les courbes LOESS, ils ne sont pas très importants. Bonne continuation.

  2. Bonjour,
    Tout d’abord merci pour votre très bon tuto.
    Une petite question : comment et-il possible d’ajouter sur chaque graphique le coefficient r2 (r-squarred) ainsi que la p-value ?

    Merci d’avance

  3. Bonjour,

    Un énorme merci pour vos explications qui sont toujours très claires et qui m’ont, encore une fois, fait gagner un temps fou!

    Karine

  4. Bonjour est t’il possible de les afficher tous en même temps via une fonction plot_grid par exemple?
    merci beaucoup
    Ninon

    1. Bonjour,

      je n’ai pas essayé, mais je pense que ça doit fonctionner. N’hesitez pas à nous partager votre code, si c’est le cas !
      Bonne continuation.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bonjour !

vous venez souvent ?

Identifiez-vous pour avoir accès à toutes les fontionnalités !

Aide mémoire off'R ;)

Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.