Home > other >  Double for loop to check dynamic number of plots in shiny app
Double for loop to check dynamic number of plots in shiny app

Time:12-31

I find myself faced with a problem:

I already have my shiny application (server part) like this :

observe({
      data <- my_function() %>%
       filter(col1 == "X1")

h <- sort(unique(data$year))

nb <- length(h)
lst <- as.list(h)

output$plot_name <- renderUI({
  plot_output <- lapply(1:nb,
                                 function(n1) {
                                   plotname <- paste0("plots", n1)
                                   plotOutput(plotname)
                                 })
  do.call(tagList, plot_output)
})

my_data <- list()

i <- 0
for (i in 1:length(lst)) {
  
  local({
    my_i <- i
    plotname <- paste0("plots", my_i)
    my_data[[my_i]] <- data %>% 
      filter(year == lst[[my_i]])
    
    output[[plotname]] <- renderPlot({
      
      g <- ggplot(..........)
      
      print(g)
      
    })
    
  })
}

})

that allows me to output, for each year, graphs for a given X.

However I would like to remove the filter and have for each year of each X a graph, knowing that I do not have the same number of years for all X (X1: 2000, X2: 2000 and 2001, X3 : 2001 etc.....).

Since I would like to determine dynamically the number of graphs.

If you have any clues, it will be very useful.

Thanks in advance.

CodePudding user response:

We can create all the plots inside a data frame and then count how many of them are they in order to create the corresponding outputs.

library(tidyverse)
library(shiny)


df <-
  read_table("col1 col2 year pts
X1 1 2000 24 
X1 2 2001 36 
X2 1 2000 48
X1 0 2000 24
X3 1 2000 72
X2 1 2000 24
X2 2 2002 48
X3 2 2001 24")



ui <- fluidPage(
  uiOutput("plot_name")
)

server <- function(input, output, session) {
  my_function <- reactive({
    df
  })
  
  observeEvent(my_function, {
    data <- my_function() 
    

# Create the plots --------------------------------------------------------

    
    plots_df <- 
      data %>% 
      group_by(col1, year) %>%
      summarise(plot = list(
        ggplot(cur_data_all() ,aes(x = pts, y = col2))  
          geom_point()  
          ggtitle(paste('col:', col1 ,'year:', year))
      ))
    

# plots UI ----------------------------------------------------------------

    
    nb <- length(plots_df$plot)
    plotname <- paste0("plots", 1:nb) # save the names for renderPlot functions

    output$plot_name <- renderUI({
      plot_output <- lapply(
        plotname,
        function(n1) {
          plotOutput(n1)
        }
      )
      do.call(tagList, plot_output)
    })


# renderPlot funcitons ----------------------------------------------------


    walk2(plotname, plots_df$plot, ~ {
      output[[.x]] <<- renderPlot({
        .y
      })
    })
   })
}

shinyApp(ui, server)
  • Related