Shiny Ggplot et Data à 200K Lignes

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Shiny Ggplot et Data à 200K Lignes

Messagepar Jean-Emmanuel Longueville » 03 Juin 2021, 14:09

Bonjour,
Je travaille sur l'élaboration d'une application pour faire (dans un premier temps) des graphiques simples avec Shiny.
Je rencontre un gros soucis de temps la réalisation de graphique ggplot avec 200k lignes étant assez longue (~20sec). Pour un jeu simmulé à deux colonnes. Mes données de bases étant plus grosses (200kl x 10 à 20cln) en fonction des tables).

Pour les motivés voici un ecm sur 200k ligne et deux colonnes :D

Code : Tout sélectionner


mod_graph2var_ui 
<- function(id){
  ns <- NS(id)
  tagList(
    pageWithSidebar(
      # title
      headerPanel("Select Options"),
      
      
#input
      sidebarPanel
      
(
        selectInput(ns("dataset"),    "Dataset"   , "NONE", selected = "NONE"),  
        selectInput
(ns("variable_x"), "Variable X", "NONE", selected = "NONE"),
        selectInput(ns("variable_y"), "Variable Y", "NONE", selected = "NONE"),
        selectInput(ns("group"),      "Coloration", "NONE", selected = "NONE"), 
        selectInput
(ns("plot_type"), "Plot Type:", 
                    list
(boxplot = "boxplot", points = "points", 
                         lines 
= "lines_")
        ),
        checkboxInput(ns("show.points"), "show points", FALSE),
        actionButton(ns("updt_graph"), "Update graph")
      ),    
      
      
# output                
      mainPanel(
        h3(textOutput(ns("caption"))),
        plotlyOutput(ns("plot_render"))
      )
    )
  )
}

#' graph2var Server Functions
#'
#' @noRd 
mod_graph2var_server <- function(id, my_tables){
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    shiny
::observe({
      #update variable and group based on dataset
      updateSelectInput(session, "dataset",
                        label = "Vue:",
                        choices = names(my_tables),
                        selected = "environment")}, priority = 1)
    shiny::observe({
      #update variable and group based on dataset
      if(!is.null(input$dataset)){
        updateSelectInput(session, "variable_x", choices = colnames(my_tables[[input$dataset]]) )
        updateSelectInput(session, "variable_y", choices = colnames(my_tables[[input$dataset]]) )
        updateSelectInput(session, "group",      choices = colnames( my_tables[[input$dataset]]) )
      }#fin de if
    })#Fin du observe
    
    
    output$caption
<- shiny::renderText({
      switch(input$plot_type,
             "boxplot"      =     "Boxplot",
             "points"    =    "Distribution",
             "lines_"      =    "Lignes"
      ) })
    
    
#plotting theme
    theme_blank<- theme(
      axis.line = element_line(colour = 'gray', size = .75),
      panel.background = element_blank(),
      plot.background = element_blank(),
      legend.position = "none"
    )
    #plotting function using ggplot2
    shiny::observeEvent(input$updt_graph, {   
      output$plot_render 
<- plotly::renderPlotly({
        isolate(
          if(input$dataset != "NONE" & input$variable_x != "NONE" & 
             input$variable_y 
!= "NONE" & input$group != "NONE" ){
            
            print
("Debug On attaque le graph")
            #dynamic plotting options
            plot_fn<-switch(input$plot_type,
                            "boxplot"    = ggplot2::geom_boxplot(),
                            "points"  =    ggplot2::geom_point(),
                            "lines_"     =    ggplot2::geom_line(),
            )
            x   <- input$variable_x
            y   
<- input$variable_y
            grp 
<- input$group
            plot_aes 
<- aes( x          = .data[[x]],
                             y          = .data[[y]],
                             color = .data[[grp]] )
            
            p
<-ggplot(my_tables[[input$dataset]]) + plot_aes + plot_fn

            
            p
<-p+labs(
              fill     = input$group,
              x         = input$variable_x,
              y         = input$variable_y
            
)  +
              theme_blank
            
            if
(input$show.points==TRUE) {
              p<-p+ geom_point(color=plot_obj$group, alpha=0.5, position = 'jitter')
            }
            print(ggplotly(p))
          }else{
            p <- ggplot() + annotate("text", x = 5, y = 5,
                                     label = "Pas de graphique maintenant") +
              theme_blank
            print
(ggplotly(p))
            print("Le graph est compilé")
          }# fin du else
        )#fin du isolate
      })#Fin du renderPlot
    })#Fin du observe updt_graph
  }) #Close module server
}# Close definition of global function : mod_graph1var_server
 
Jean-Emmanuel
Ingénieur d'étude LNEC

Sébastien Rochette
Messages : 54
Enregistré le : 03 Juil 2020, 12:43
Contact :

Re: Shiny Ggplot et Data à 200K Lignes

Messagepar Sébastien Rochette » 03 Juin 2021, 14:20

Bonjour,

Ce n'est pas spécialement lié à Shiny, c'est ggplot2 lui-même qui prend du temps.
Au moins 3 possibilités s'offrent à toi,

- Tu peux changer les graphiques pour qu'il affichent moins de données. Je ne crois pas que l'oeil humain soit capable de distinguer 200K données. Il y a probablement des manières d'optimiser les données à afficher, soit avec des échantillons bien choisis, soit avec des pré-calculs des valeurs clés (médiane, max, min, ...). Dans tous les cas, cette recherche peut se faire dans un Rmd à côté

- Tu peux faire en sorte que l'app soit toujours utilisable même si un calcul de graphique est en cours, en faisant des "promises". Et donc en décalant l'affichage au moment où c'est dispo: https://rstudio.github.io/promises/articles/shiny.html

- Enfin, tu peux utiliser les nouvelles capacités de Shiny 5 à faire du cache et donc à mettre les graphiques en cache, de telle sorte que si on redemande la même combinaison de variables, le graph ne soit pas recalculé, mais affiché avec le cache. La façon de gérer le cache, dépend de la manière dont tu met l'app en prod. Avec un Shinyproxy, ce sera différent d'un Connect par exemple. Pour gérer du cache partagé, on a commencé à développer un package: https://github.com/thinkr-open/bank
Sébastien
Dev, Consult, Formateur
ThinkR

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Shiny Ggplot et Data à 200K Lignes

Messagepar Mickael Canouil » 03 Juin 2021, 15:07

Bonjour,

a priori, c'est surtout le geom_point qui prend du temps, si les points de façon individuelle ne sont pas exploités, peut-être que l'usage des geom_density_2d (https://ggplot2.tidyverse.org/reference ... ty_2d.html) serait une solution pour réduire le nombre d'élément à afficher.

Cordialement,
Mickaël
mickael.canouil.fr | rlille.fr

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Re: Shiny Ggplot et Data à 200K Lignes

Messagepar Jean-Emmanuel Longueville » 04 Juin 2021, 13:21

Merci pour vos réponses, en cherchant comment faire j'ai trouvé le projet Radiant qui corresponds totalement à notre besoin.
Jean-Emmanuel
Ingénieur d'étude LNEC


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité

cron