Présentation Shiny

Solenne Roux

Shiny

Ensemble de fonctions permettant de développer des applications web

interactives

basées sur des packages R Shiny

Existe aussi en Python depuis 2022

D’où ça vient ?

Développé par Posit (Rstudio) en 2012

Qu’est-ce qu’on peut faire ?

Un classique

library(shiny)

ui <- fluidPage(
  textInput("name", "What is your name?"),
  textOutput("greeting")
)

server <- function(input, output, session) {
  output$greeting <- renderText({paste0("Hello ", input$name)})
 } 

shinyApp(ui, server)

Un classique bien pratique

if (!require("pacman")) install.packages("pacman")
pacman::p_load(bslib, shiny, shinylive, shinythemes, shinydashboard)

ui <- page_sidebar(

  title = "Importance de la taille d'échantillon",

  sidebar = sidebar(

    radioButtons(
      "dist",
      "Loi de distribution:",
      c(
        "Normale" = "norm",
        "Uniforme" = "unif",
        "Log-normale" = "lnorm",
        "Exponentielle" = "exp"
      )
    ),
    
    br(),

    numericInput(
      "n",
      "Nombre d'observations:",
      value = 300,
      min = 1,
      max = 10000
    )
  ),

  navset_card_underline(

    nav_panel("Plot", plotOutput("plot")),

    nav_panel("Summary", verbatimTextOutput("summary")),

    nav_panel("Table", tableOutput("table")), 
    
    nav_panel("Télécharger les données", downloadButton("Data","Télécharger les données"))
  )
)

server <- function(input, output) {

  d <- reactive({
    dist <- switch(
      input$dist,
      norm = rnorm,
      unif = runif,
      lnorm = rlnorm,
      exp = rexp,
      rnorm
    )

    dist(input$n)
  })

  output$plot <- renderPlot({
    dist <- input$dist
    n <- input$n

    hist(
      d(),
      main = paste("r", dist, "(", n, ")", sep = ""),
      col = "aquamarine",
      border = "white"
    )
  })

  output$summary <- renderPrint({
    summary(d())
  })

  output$table <- renderTable({
    d()
  })

 output$Data <- downloadHandler(
  filename = function() {
    "Data.csv"
  },
  content = function(file) {
    write.csv2(d(), file, row.names = FALSE)
  }
)

}

shinyApp(ui, server) 

Un exemple avec des données

if (!require("pacman")) install.packages("pacman")
pacman::p_load(bslib, dplyr, ggplot2, here, readxl, shiny, shinylive, shinythemes, shinydashboard)

DF_path <- here("data", "DF_ERFI_anonym.xlsx")
DF <- read_excel(DF_path)

DF$OA_SATREP <- as.numeric(DF$OA_SATREP)
DF$MA_SEXE <- as.factor(DF$MA_SEXE)
DF2 <- subset(DF, select = c(OA_SATREP, MA_SEXE))
DF2 <- na.omit(DF2)

levels(DF2$MA_SEXE) <- c("Hommes", "Femmes")

# UI
ui <- fluidPage(
  theme = shinytheme("flatly"),
  titlePanel("Histogramme de la satisfaction de la répartition des tâches ménagères selon le genre"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "gender",
        label = "Sélectionner le genre :",
        choices = c("Tous" = "Tous", "Hommes" = "Hommes", "Femmes" = "Femmes"),
        selected = "Tous"
      )
    ),
    mainPanel(
      plotOutput("histPlot", height = "500px")
    )
  )
)

# Server
server <- function(input, output) {
  output$histPlot <- renderPlot({
    filtered_data <- DF2
    if (input$gender != "Tous") {
      filtered_data <- DF2 %>% filter(MA_SEXE == input$gender)
    }
    
    if (input$gender == "Tous") {
      p <- ggplot(filtered_data, aes(x = OA_SATREP, fill = MA_SEXE)) +
        geom_histogram(bins = 30, position = "dodge") +
        facet_wrap(~ MA_SEXE, ncol = 2) +
        labs(
          title = "Histogramme de la satisfaction (Tous)",
          x = "Satisfaction de la répartition des tâches ménagères",
          y = "Fréquence"
        ) +
        theme_minimal() +
        scale_fill_manual(values = c("Hommes" = "aquamarine", "Femmes" = "steelblue"))
    } else {
      gender_color <- if (input$gender == "Hommes") "aquamarine" else "steelblue"
      p <- ggplot(filtered_data, aes(x = OA_SATREP)) +
        geom_histogram(bins = 30, fill = gender_color, color = "black") +
        labs(
          title = paste("Histogramme de la satisfaction (", input$gender, ")", sep = ""),
          x = "Satisfaction de la répartition des tâches ménagères",
          y = "Fréquence"
        ) +
        theme_minimal() +
        theme(legend.position = "none")
    }
    
    print(p)
  })
}

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

Les éléments de base

if (!require("pacman")) install.packages("pacman")
pacman::p_load(shiny, shinylive, shinythemes, shinydashboard)


  ui <- # Ce que l'on souhaite voir en entrée

  server <- function(input, output) {
    # Ce qui va s'exécuter et s'afficher
  }

    
shinyApp(ui, server) # Ce qui permet à l'application Shiny de s'exécuter en prenant en compte l'input et l'output

Les options

L’organisation de la page

  • page_sidebar() : pour afficher un menu sur le côté

  • page_navbar() : pour afficher plusieurs pages avec un menu (comme un site web)

  • nav_panel() : permet d’intégrer des onglets

  • accordion() : permet d’avoir des éléments dépliants ou non

Les options

Différents styles de navigation grâce au package bslib :

  • navset_underline() and navset_card_underline() : permet d’intégrer une vue sous forme de tableau avec une barre de navigation horizontale avec des boutons cliquables soulignés (à la place d’onglets)
  • navset_tab() and navset_card_tab() : permet d’intégrer une vue sous forme de tableau avec une barre de navigation horizontale avec des onglets
  • navset_pill_list() : permet de créer une barre de navigation verticale
  • navset_pill() and navset_card_pill() : permet d’intégrer une vue sous forme de tableau avec une barre de navigation horizontale avec des boutons cliquables (à la place d’onglets)

Différents inputs :

  • radioButtons() : choix à l’aide de bouton radio
  • numericInput() : choix à entrée numérique
  • sliderInput() : choix avec un curseur
  • selectInput() : choix dans un menu déroulant
  • textInput() : champs texte
  • checkboxInput() : case à cocher
  • dateInput() : sélectionner une date
  • dateRangeInput() : sélectionner une période
  • fileInput() : téléverser un fichier

Différents outputs :

Avec 2 niveaux :

  • Niveau entrée utilisateur (UI)

    • plotOutput() : permet de créer l’affichage d’un graphique interactif
    • dataTableOutput() : permet de créer l’affichage d’un tableau de données de façon dynamique
    • tableOutput() : permet de créer l’affichage d’un tableau
    • textOutput() : permet de créer l’affichage d’un texte
    • downloadButton() : permet de télécharger des données

Différents outputs :

Avec 2 niveaux :

  • Niveau affichage (server)

    • renderPlot() : permet d’afficher un graphique interactif
    • renderDataTable() : permet d’afficher un tableau de données de façon dynamique
    • renderPrint() : permet d’afficher une sortie (comme print())
    • renderTable() : permet d’afficher un tableau
    • renderText() : permet d’afficher du texte

Thèmes

Avec le package bslib et la fonction bs_theme()

Compatibles avec le package R markdown et basé sur le package Bootswatch

Images, texte et cartes

Possibilité d’afficher des images dans une shiny app avec imageOutput() et valueBox()

et du texte avec textOutput() et renderText()

ainsi que des cartes avec leafletOutput() et renderLeaflet()

Boutons

Boutons actifs avec actionButton() et

un lien avec actionLink()

Tableaux de bord

shinydashboard()

library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Basic dashboard"),
  dashboardSidebar(),
  dashboardBody(
    # Boxes need to be put in a row (or column)
    fluidRow(
      box(plotOutput("plot1", height = 250)),

      box(
        title = "Controls",
        sliderInput("slider", "Number of observations:", 1, 100, 50)
      )
    )
  )
)

server <- function(input, output) {
  set.seed(122)
  histdata <- rnorm(500)

  output$plot1 <- renderPlot({
    data <- histdata[seq_len(input$slider)]
    hist(data)
  })
}

shinyApp(ui, server)

Tableaux de bord

flexdashboard()

Tableaux de bord

flexdashboard()

Tableaux de bord

flexdahboard

Age selon le sexe

if (!require("pacman")) install.packages("pacman")
pacman::p_load(bslib, dplyr, ggplot2, here, readxl, shiny, shinylive, shinythemes, shinydashboard)

DF_path <- here("data", "DF_ERFI_anonym.xlsx")
DF <- read_excel(DF_path)

DF$OA_SATREP <- as.numeric(DF$OA_SATREP)
DF$MA_SEXE <- as.factor(DF$MA_SEXE)
DF2 <- subset(DF, select = c(OA_SATREP, MA_SEXE))
DF2 <- na.omit(DF2)

      selectInput(
        inputId = "gender",
        label = "Sélectionner le genre :",
        choices = c("Tous" = "Tous", "Hommes" = "1", "Femmes" = "2"),
        selected = "Tous"
      )
renderPlot({
    filtered_data <- DF2
    if (input$gender != "Tous") {
      filtered_data <- DF2 %>% filter(MA_SEXE == input$gender)
    }
    
    ggplot(filtered_data, aes(x = OA_SATREP, fill = MA_SEXE)) +
      geom_histogram(bins = 30, position = "dodge") +
      facet_wrap(~ MA_SEXE, ncol = 2) +
      labs(
        title = paste("Histogrammes de la satisfaction (", input$gender, ")", sep = ""),
        x = "Satisfaction de la répartition des tâches ménagères",
        y = "Fréquence"
      ) +
      theme_minimal()
  })

Tableau de bord avec flexdashboard

Cet exemple est accessible ici.

Quarto dashboard

Quarto dashboard

Cet exemple est accessible ici.

Déployer sa shiny app

Connecter son instance Rstudio avec celle de shinyapps de Posit

Connexion

Déploiement