TP Shiny

Plateforme Migale

Author

Sandra Derozier - Mahendra Mariadassou - Cédric Midoux

Published

March 14, 2025

Shiny, c’est parti !

  • Créez une application Shiny avec RStudio : File > New File > Shiny Web App.
  • Donnez un nom à votre première application et enregistrez-la dans le dossier de votre choix avec l’option “Single File”.
  • Parcourez et exécutez le code suivant :
#
# 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, ajoutez une phrase précisant le nombre de bins.

app2.R

Choisir un titre

  • Ajoutez un champ texte permettant à l’utilisateur de choisir le titre de l’application dans titlePanel.

app3.R

Un peu de couleur

  • Ajoutez des boutons radio pour choisir la couleur parmi : "darkgray", "coral", "lightgreen".

app4.R

Plusieurs onglets

  • Ajoutez des onglets dans le mainPanel() avec tabsetPanel() :
    • Premier onglet : histogramme.
    • Deuxième onglet : boxplot.
    • Troisième onglet : tableau des données.

app5.R

Personnalisation avec CSS

  • Modifiez l’apparence de l’application en ajoutant un fichier styles.css dans 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.
  • Remplacez les données par un tirage aléatoire de 10 valeurs x <- rnorm(10).
  • Que se passe-t-il en changeant 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 : utilisation de datasetInput()

  • 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”.
  • Supprimez la ligne correspondante (x <- faithful[, 2]) de la fonction et remplacez-la 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 telle que :

datasetInput <- reactive({ faithful$waiting })
  • Testez l’application et vérifiez que tout fonctionne toujours. Essayez 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, proposez 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).
  • Mettez à jour datasetInput() en fonction de ce choix.
    • Note : on peut utiliser un enchaînement de else if ou bien la fonction switch.

app7.R

Données générées aléatoirement

  • Ajoutez un choix dans la liste correspondant à un tirage aléatoire de 100 valeurs distribuées normalement.
  • Ajoutez un champ dédié dans la liste déroulante.
  • Mettez à 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, ajoutez une section dédiée aux paramètres du tirage (n, mean, sd).

  • Bonus : affichez 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 : ajoutez 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 : remplacez 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

  • Ajoutez la possibilité à l’utilisateur d’uploader un fichier CSV (ex data.csv).
    • ajoutez un champ dédié dans la liste déroulante
    • ajoutez un widget d’upload
    • Aide R : utilisez 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’agit 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 : Anticipez l’erreur d’un fichier non sélectionné avec validate() et need() ainsi que l’opérateur booléen OR ||

app10.R
app10bonus.R

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))
})
  • Ajoutez 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.
  • Remplacez 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.
ggplot(data = datasetInput(), aes_string(x = input$variable)) +
    geom_histogram(bins = input$bins, fill = input$color, color = "white")

ggplot(data = datasetInput(), aes_string(y = input$variable)) +
    geom_boxplot(fill = input$color)

app11.R

Téléchargement du graphique

  • Ajoutez un bouton pour télécharger le plot avec 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).

    • choisissez une feuille de style sur Bootswatch
    • téléchargez le fichier bootstrap.css dans le dossier www/ de votre appli
    • indiquez 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éez un compte sur shinyapps.io.
  • Définissez un nom de domaine. Vos applications apparaîtront via https://<domaine>.shinyapps.io/<appli>/.
  • Rendez-vous sur la page d’administration et suivez les étapes afin de connecter votre RStudio local à votre compte grâce à rsconnect.
  • Cliquez sur l’icône Publish publish.
  • Sélectionnez les fichiers à publier, définissez un nom et cliquez 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