TP Shiny

Plateforme Migale

Author

Sandra Derozier - Mahendra Mariadassou - Cédric Midoux

Published

March 18, 2022

Shiny, c’est parti !

  • Créer une application shiny avec RStudio File > New File > Shiny Web App.

  • Donner un nom à votre première application et enregistrer la dans le dossier de votre choix avec le choix “Single File”.

  • Parcourir et exécuter le code :

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    titlePanel("Old Faithful Geyser Data"),

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
            sliderInput("bins",
                        "Number of bins:",
                        min = 1,
                        max = 50,
                        value = 30)
        ),

        # Show a plot of the generated distribution
        mainPanel(
           plotOutput("distPlot")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

    output$distPlot <- renderPlot({
        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)

        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

app.R

Ajouter du texte

  • Sous la figure, ajouter une phrase précisant le nombre de bins.

app2.R

Choisir un titre

  • Ajouter un champs texte pour laisser à l’utilisateur le choix du titre de l’application titlePanel.

app3.R

Un peu de couleur

  • Ajouter des boutons radio permettant de choisir parmi les couleurs "darkgray", "coral", "lightgreen".

app4.R

Plusieurs onglets

  • Ajouter des onglets dans le mainPanel() avec l’aide de la fonction tabsetPanel()
    • le premier onglet : un histogramme
    • le second onglet : un boxplot
    • le troisième onglet : un tableau des données

app5.R

  • Changement de look pour notre application via l’utilisation d’un fichier CSS styles.css déposé dans le répertoire www
    • mettre en avant le titre de l’application en lui attribuant une couleur (darkblue par exemple)
    • mettre en avant les labels des éléments présents dans le sidebarPanel (purple par exemple)
    • distinguer davantage l’onglet sélectionné en changeant la couleur du texte (darkblue par exemple) et en passant le texte en gras (font-weight=bold)

app5_bis.R / styles.css

Un peu d’aléatoire

  • Actuellement, notre plot affiche les données des durées entre deux éruptions du geyser Old Faithful.
  • Remplacer les données par un tirage aléatoire de 10 valeurs x <- rnorm(10).
  • Que se passe-t-il lorsque l’on change la couleur du plot ? Est-ce que les différents onglets représentent les mêmes données ? Que proposez-vous pour résoudre cela ?

De nouvelles données

  • Actuellement, les données sont directement gérées au sein de la fonction du plot.
  • On va chercher à séparer le côté “données”, du côté “figures”.
  • Supprimer la ligne correspondante (x <- faithful[, 2]) de la fonction et la remplacer par un appel à l’expression réactive datasetInput() (x <- datasetInput()) qui permettra de gérer les données de manière dynamique et réactive. Avant le renderPlot, on définit l’expression réactive datasetInput tel que :
datasetInput <- reactive({faithful$waiting})
  • Tester l’application et vérifier que tout fonctionne toujours. Essayer de comprendre et d’assimiler l’articulation des différents éléments. > app6.R

  • Maintenant que tout est fonctionnel, à l’aide d’une liste déroulante, proposer le choix entre la durée des éruptions du geyser Old Faithful (faithful$waiting), la longueur des sépales des iris de Fisher (iris$Sepal.Length) ou la puissance des voitures d’après Motor Trend (mtcars$hp). Mettre mettre à jour datasetInput() en fonction de ce choix.

    • Note : on peut utiliser un enchaînement de else if ou bien la fonction switch.

app7.R

Des données générées aléatoirement

  • Ajouter un choix dans la liste correspondant à un tirage aléatoire de 100 valeurs distribuées normalement.
    • ajouter un champ dédié dans la liste déroulante
    • mettre à jour les données afin de renvoyer rnorm(100) si random est sélectionné dans le champ data.
  • Note : le reactive() ne dépend pas des inputs du choix de couleur ou du nombre de bins. Le tirage aléatoire ne change donc pas lorsque la couleur ou les bins sont modifiés.

app8.R

Paramètres du tirage aléatoire

  • Dans la barre de paramètres, ajouter une section dédiée aux paramètres du tirage (n, mean, sd).

  • Bonus : afficher ces paramètres uniquement lorsque l’on sélectionne les données aléatoires dans la liste déroulante (voir conditionalPanel, attention à la syntaxe).

  • Bonus : ajouter un bouton “Relancer” qui permet de relancer le tirage des données aléatoires lorsqu’on clique dessus.

  • Note : la solution proposée utilise des reactiveVal(), c’est à dire des variables réactives dont vous pouvez contrôler manuellement la mise à jour en plus de son caractère réactif (via un observeEvent() ou un observe() %>% bindEvent())

  • Bonus : remplacer le bouton “Relancer” par un bouton “Confirmer / Relancer” qui force l’utilisateur à confirmer son choix de paramètres (n, mean, sd) avant de générer les données aléatoires

  • Note : la stratégie possible consiste à utiliser 2 reactive() enchaînés (dont un soumis à un bindEvent()) et le choix apparaît clairement lorsqu’on trace le graphe de réactivité.

app9.R
app9_bis.R
app9_ter.R

Téléchargement de données

  • Permettre à l’utilisateur de charger ses données au format CSV.
    • ajouter un champ dédié dans la liste déroulante
    • ajouter un widget d’upload
    • Aide R : utiliser la fonction read.csv(file, header = FALSE)[,1] pour extraire la première colonne.
    • Note : input$file est un data.frame qui continent 4 éléments :
      • name : Le nom du fichier. Il ne s’aggit pas du chemin complet.
      • size : La taille du fichier téléchargé, en octets.
      • type : Le type du fichier ou un string vide si le navigateur ne le sait pas.
      • filepath: Le chemin d’accès à un fichier temporaire qui contient les données téléchargées. Ce fichier peut être supprimé si l’utilisateur effectue une autre opération de téléchargement. C’est cette variable qu’il faudra utiliser pour acédéer aux données.


  • Bonus : anticiper l’erreur du fichier non sélectionné avec les fonctions validate() et need() anisi que l’opérateur booléen OR ||

app10.R
app10bonus.R

Des data.frames et ggplot2 pour des graphiques élégants

  • ggplot2 comme de nombreux autres packages R utilise les dataframes. On va donc exploiter nos données avec ce format.
    • pour les données de démo faithful, iris et mtcars, ce sont des dataframes
    • pour les données chargées par l’utilisateur, il s’agit d’un dataframe avant que l’on extrait la première colonne
    • pour les données générées aléatoirement on va construire sous le format data.frame
  • Remplacer le reactive datasetInput par :
datasetInput <- reactive({
    switch(input$data,
           "faithful" = faithful,
           "iris" = iris,
           "mtcars" = mtcars,
           "random" = data.frame("rnorm" = rnorm(n = input$randomN, mean = input$randomMean, sd = input$randomSd)),
           "upload" = read.csv(input$file$datapath, header = TRUE))
})
  • Ajouter un widget varSelectInput destiné à sélectionner une variable
    • pour que ce widget se mette à jour en fonction des données choisies, il est nécessaire de le placer côté “server”.
    • pour l’afficher coté UI, on utilisera uiOutput qui renverra vers le renderUI associé où sera placé le widget.
  • Remplacer l’histogramme et le boxplot par l’équivalent en ggplot2. Le sujet du TP n’étant pas spécialement l’utilisation de ggplot2, voici directement les fonctions. Si vous êtes à l’aise, laissez libre cours à votre imagination pour les personnaliser.
    • Histogramme : ggplot(data = datasetInput(), aes_string(x = input$variable)) + geom_histogram(bins = input$bins, fill = input$color, color = "white")
    • Boxplot : ggplot(data = datasetInput(), aes_string(y = input$variable)) + geom_boxplot(fill = input$color)

app11.R

Téléchargement d’un plot

  • Ajouter un bouton pour télécharger le plot grâce aux fonctions downloadHandler et ggsave.

Note : pour que le téléchargement se lance correctement, lancer l’application dans un “vrai” navigateur. Utiliser la commande :

runApp('app11.R', launch.browser = TRUE) 

app12.R

Mise en forme avec CSS

  • On peut facilement mettre en forme l’interface utilisateur d’une application avec CSS (cascading style sheets).

    • choisir une feuille de style sur Bootswatch
    • télécharger le fichier bootstrap.css dans le dossier www/ de votre appli
    • indiquer le thème avec theme = "bootstrap.css" dans la fonction fluidPage()

app13.R avec un fichier bootstrap.css dans le dossier www/

Déploiement d’une application avec shinyapps.io

  • Créer un compte sur https://www.shinyapps.io/.
  • Définir un nom de domaine. Vos applications apparaîtront via https://<domaine>.shinyapps.io/<appli>/.
  • Rendez-vous sur la page d’administration et suivre les étapes afin de connecter votre RStudio local à votre compte grâce à rsconnect.
  • Cliquer sur l’icône Publish publish.
  • Sélectionner les fichiers à publier, définir un nom et cliquer sur “Publish”.
  • Note : Votre application doit s’appeler app.R ou bien ui.r+server.R.
  • C’est fini !

A work by Migale Bioinformatics Facility
Université Paris-Saclay, INRAE, MaIAGE, 78350, Jouy-en-Josas, France
Université Paris-Saclay, INRAE, BioinfOmics, MIGALE bioinformatics facility, 78350, Jouy-en-Josas, France