Le package shiny permet de développer très facilement des applications web à partir de R. Grâce à cette librairie, et d’autres librairies R dédiées comme ggplot2 et flexdashboard, il est ainsi possible de générer des tableaux de bord, introduisant même des méthodes statistiques approfondies.

Pour notre premier TP, nous allons utiliser le jeu de données mtcars présent sous R.

Application

Une application quelle qu’elle soit fait intervenir des notions importantes à comprendre pour la suite :

  • Développeur : créateur(s) de l’application (vous en l’occurence dans la suite)
  • Utilisateur : personnes accédant à l’application et intéragissant avec elle
  • Interface (UI) : ensemble des éléments visibles par l’utilisateur, comprenant
    • Entrées (inputs) : boutons, listes de sélections, zone de saisie que l’utilisateur pourra modifier
    • Sorties (outputs) : éléments générés automatiquement par l’application, directement ou à partir des choix faits par l’utilisateur (cf entrées)
  • Exécution : calcul des éléments de sorties à partir des éléments d’entrées

Première application

Une application shiny nécessite une organisation spécifique. Les fichiers doivent être nommés spécifiquement, et dans un répertoire déterminé. Les deux fichiers sont :

  • server.R : définissant les opérations à réaliser (exécution) lors de la création de la page et lors des différentes interactions de l’utilisateur ;
  • ui.R : définissant l’interface utilisateur (UI signifiant User Interface), avec les différentes parties telles que le titre, les différentes boutons ou sélecteurs, et les graphiques et/ou textes.

Il est aussi possible de n’avoir qu’un seul fichier. Dans ce cas, celui-ci doit s’appeler app.R et contient les deux éléments ci-dessus.

Dans le répertoire peut aussi être présents des scripts R classiques, des données au format RData ou texte (ou autre), ainsi que tout ce qui est nécessaire à l’application.

Vous devez d’abord installer la librairie shiny (cf TPs précédents). Il est possible de créer automatiquement une application via le menu, mais nous allons le faire manuellement afin de mieux comprendre le fonctionnement de la librairie.

Page simple avec un titre

Dans un nouveau répertoire créé spécifiquement, vous devez créer les deux fichiers R avec strictement le contenu suivant :

  • server.R :
library(shiny)

shinyServer(function(input, output) {})
  • ui.R :
library(shiny)

shinyUI(fluidPage(
  titlePanel("Première application")
))

Une fois ces fichiers enregistrés, pour voir le résultat, vous pouvez soit cliquer sur Run App en haut à droite de l’éditeur de texte, soit exécuter la commande runApp() dans la console. Vous devriez voir une fenêtre avec juste le titre qui s’affiche.

Ajout d’un graphique

On va ajouter un nuage de points entre la variable mpg (consommation en Miles/US Gallon) et wt (poids) du jeu de données mtcars. Il faut donc modifier les deux fichiers dont le contenu devient :

  • server.R :
library(shiny)

shinyServer(function(input, output) {
  output$nuage <- renderPlot({
    plot(mpg ~ wt, data = mtcars, main = "Consommation en fonction du poids")
  })
})
  • ui.R :
library(shiny)

shinyUI(fluidPage(
  titlePanel("Première application"),
  plotOutput("nuage")
))

Que faut-il noter ?

  • On ajoute dans l’interface une zone, nommée nuage qui sera une sortie graphique (plotOutput) ;
  • On définit le contenu de cette zone (output$nuage) comme étant un rendu graphique (renderPlot), dans lequel on met du code R permettant de faire un graphique. Le code ici présent est tou ) fait classique.

Ajout d’un bouton d’action

On ajoute ici un bouton permettant de sélectionner la variable de l’axe \(x\) (wt dans notre exemple). Nous allons laisser à l’utilisateur le choix entre wt, hp (puissance) et disp (cylindrée). Il faut donc modifier les deux fichiers :

  • server.R :
library(shiny)

shinyServer(function(input, output) {
  output$nuage <- renderPlot({
    plot(mtcars$mpg ~ mtcars[,input$choix], main = "Consommation")
  })
})
  • ui.R :
library(shiny)

shinyUI(fluidPage(
  titlePanel("Première application"),
  selectInput("choix", "Abscisse", c("wt", "hp", "disp")),
  plotOutput("nuage")
))

Que faut-il noter ?

  • Dans l’interface, on ajoute une zone de sélection (selectInput) nommée choix, avec un titre (Abscisse) et donc une liste de choix (c("wt", "hp", "disp")) ;
  • Côté serveur, on redéfinit le graphique pour qu’il s’adapte automatiquement à la sélection de l’utilisateur. Pour cela, on se base sur le fait que la sélection (input$choix) sera une chaîne de caractère parmi les trois proposées. La commande mtcars[,input$choix] renverra donc bien le vecteur de la colonne choisie par l’utilisateur.

A tester : changer le titre de l’axe des abcisses pour afficher le nom de la variable choisie (cf paramètre xlab dans la fonction plot).

Ajout d’une zone de texte

On souhaite ajouter maintenant le calcul automatique de la moyenne des deux variables sélectionnées. Pour cela, nous allons modifier le contenu des fichiers comme suit :

  • server.R :
library(shiny)

shinyServer(function(input, output) {
  output$nuage <- renderPlot({
    plot(mtcars$mpg ~ mtcars[,input$choix], main = "Consommation")
  })
  
  output$resumeMpg <- renderText({
    paste("Moyenne mpg :", mean(mtcars$mpg, na.rm = T))
  })
  output$resumeVar <- renderText({
    paste("Moyenne", input$choix, ":", mean(mtcars[,input$choix], na.rm = T))
  })
})
  • ui.R :
library(shiny)

shinyUI(fluidPage(
  titlePanel("Première application"),
  selectInput("choix", "Abscisse", c("wt", "hp", "disp")),
  plotOutput("nuage"),
  textOutput("resumeMpg"),
  textOutput("resumeVar")
))

Que faut-il noter ?

  • Côté utilisateur, on a ajouter deux zones de texte (textOutput), nommées resumeMpg pour la moyenne de la consommation, et resumeVar pour la moyenne de l’autre variable ;
  • Dans le serveur, on définit le texte qu’on affiche comme une concaténation de chaîne avec le calcul de la moyenne de la variable.

A tester : ajouter, dans le même esprit, le coefficient de corrélation entre les deux

Ajout d’un tableau

On peut ajouter aussi des informations sous forme de tableau. Voici les nouveaux contenus à placer dans les fichiers :

  • server.R :
library(shiny)

shinyServer(function(input, output) {
    output$nuage <- renderPlot({
        plot(mtcars$mpg ~ mtcars[,input$choix], main = "Consommation")
    })
    
    output$resumeMpg <- renderText({
        paste("Moyenne mpg :", mean(mtcars$mpg, na.rm = T))
    })
    output$resumeVar <- renderText({
        paste("Moyenne", input$choix, ":", mean(mtcars[,input$choix], na.rm = T))
    })
    
    output$tableau <- renderTable({
        sub = subset(mtcars, select = c("mpg", input$choix))
        sapply(sub, summary)
    })
})
  • ui.R :
library(shiny)

shinyUI(fluidPage(
    titlePanel("Première application"),
    selectInput("choix", "Abscisse", c("wt", "hp", "disp")),
    plotOutput("nuage"),
    textOutput("resumeMpg"),
    textOutput("resumeVar"),
    tableOutput("tableau")
))

Que faut-il noter ?

  • On a ajouté dans l’interface utilisateur une zone pour le tableau (tableOutput) ;
  • Et du côté serveur, on a fait en sorte de renvoyer un tableau (avec renderTable), celui-ci devant soit un data.frame, soit un matrix.

A tester : utiliser dataTableOutput et renderDataTable à la place des deux fonctions ci-dessus, pour voir la différence de présentation.

Un peu de mise en page

La fonction sidebarLayout() permet de prévoir une mise en page en deux zones :

  • une zone servant à faire des sélections ou des actions ;
  • une zone principale, où le rendu sera dépendant des choix faits.

On ne modifie ici que le fichier d’interface.

  • ui.R
library(shiny)

shinyUI(fluidPage(
  titlePanel("Première application"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("choix", "Abscisse", c("wt", "hp", "disp")),
      textOutput("resumeMpg"),
      textOutput("resumeVar"),
      tableOutput("tableau")
    ),
    mainPanel(
      plotOutput("nuage")
    )
  )
))

Que faut-il noter ?

  • La commande sidebarLayout permet donc de définir cette séparation en deux parties (environ 1/3-2/3). Elle doit contenir deux choses :
  • la commande sidebarPanel qui contient les éléments qui seront donc à gauche par défaut
  • la commande mainPanel qui sera celle à droite et prenant le plus de place
  • On peut mettre la partie sidebarPanel à droite avec sidebarLayout(position = "right", ..., ...)

A tester :

  • passer le tableau dans la partie droite
  • mettre la zone de sélection (sidebarPanel) à droite

A FAIRE

Dans la partie interface, il est possible de créer un système d’onglet permettant d’avoir plusieurs parties dans l’application. Voici la nouvelle partie interface utilisateur (ui.R). Vous verrez ainsi le fonctionnement des onglets.

library(shiny)

shinyUI(fluidPage(
    titlePanel("Première application"),
    
    tabsetPanel(
        tabPanel("Panel1",
                 titlePanel("titre Panel 1"),
                 
                 # Travail fait précédemment
                 sidebarLayout(
                     sidebarPanel(
                         selectInput("choix", "Abscisse", c("wt", "hp", "disp")),
                         textOutput("resumeMpg"),
                         textOutput("resumeVar"),
                         tableOutput("tableau")
                     ),
                     mainPanel(
                         plotOutput("nuage")
                     )
                 )
        ),
        tabPanel("Panel2",
                 titlePanel("titre Panel 2")
                 
                 # autre chose
        )
        # autres onglets possibles
    )
))

Vous devez donc continuer l’application, avec le contenu suivant :

  • Premier onglet
    • Le travail fait précédemment
  • Deuxième onglet : Analyse de variables qualitatives
    • l’utilisateur peut choisir une variable parmi cyl, vs, am, gear et carb
    • le système affiche le diagramme en barres et le diagramme circulaire, ainsi qu’un tableau des occurences et des fréquences des modalités
  • Troisième onglet : croisement de variables qualitatives
    • l’utilisateur doit donc choisir deux variables parmi celles citées (on ne gère pas la possibilité que l’utilisateur choisisse la même deux fois pour le moment)
    • le système affiche un diagramme en barres empilées ainsi que le tableau de contingence, avec les sommes en lignes et en colonnes