Shiny - Generate Plots with actionButton

I'm trying to write a script where the user can create up to 4 graphs (here by manipulating the x and y axis) when they click "Add Graph" . So far I've created a reactiveVal that is either 1,2,3,4 which can potentially correspond to which of the 4 plots the inputs should be mapped to but I'm having a bit of trouble coding this and was looking for some help/advice?

Desired Output

library(shiny)
library(ggplot2)
# devtools::install_github("thomasp85/patchwork")
library(patchwork)
ui <- fluidPage(
  
  titlePanel("4 Plot Generator"),
  
  sidebarLayout(
    
    sidebarPanel(
      div("Select an x and y then click Add Graph to plot. You can plot and compare up to 4 graphs.
          To reset the plots click Reset Graphs", style="text-align:center;"),
      fluidRow(
        column(6, selectInput("x_iris", "X:", choices= c(unique(colnames(iris))))),
        column(6, selectInput("y_iris", "Y:", choices = c(unique(colnames(iris)))))
      ),
      
      # button to add graph
      # button to remove graph
      fluidRow(
        column(6, actionButton("add_graph", "Add Graph")),
        column(6, actionButton("reset_graph", "Reset Graphs"))
      )
      
    ),
    
    # Show graph
    mainPanel(
      plotOutput("plots")
    )
  )
)


server <- function(input, output) {
  
  # assign graph to reactive value? 
  current_graph <- reactive({ 
    ggplot(iris, aes(x = input$x_iris, y = input$y_iris)) + 
      geom_point() 
    })
  
  # create reactive value which keeps track of add-graph (1-4)
  p <- reactiveVal(0)
  
  observeEvent(input$add_graph, {
    update_p <- ifelse(p() < 4, (p() + 1), 1)
    p(update_p)
    
# the part of the code I need help with.....
    if (p() == 1) {
      p1 <- current_graph()
      p2 <- plot_spacer()
      p3 <- plot_spacer()
      p4 <- plot_spacer()
    } else if (p() == 2) {
      p1 <- # 1st graph
      p2 <- current_graph()
      p3 <- plot_spacer()
      p4 <- plot_spacer()
    } else if (p() == 3) {
      p1 <- # 1st graph
      p2 <- # 2nd graph
      p3 <- current_graph()
      p4 <- plot_spacer()
    } else {
      p1 <- # 1st graph
      p2 <- # 2nd graph
      p3 <- # 3rd graph
      p4 <- current_graph()
    }
                         
    output$plots <- renderPlot({
      p1 + p2 + p3 + p4
    })
  })
  
  observeEvent(input$reset_graph,{
    output$plots <- renderPlot({
      NULL
    })
  })
  
  
}

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

I'd appreciate any help!!

Hi @MayaGans. I suggest the following code which using cowplot to plot the grid. A reactiveValues was created to store all valuable including plots. Use switch to trigger to assign different plots and plot grid with plot_grid. Reset all plot by assigning NULL to all plots and reset p to 1.

library(shiny)
library(ggplot2)
library(tidyverse)
library(cowplot)
# devtools::install_github("thomasp85/patchwork")
# library(patchwork)
ui <- fluidPage(
 
 titlePanel("4 Plot Generator"),
 
 sidebarLayout(
  
  sidebarPanel(
   div("Select an x and y then click Add Graph to plot. You can plot and compare up to 4 graphs.
          To reset the plots click Reset Graphs", style="text-align:center;"),
   fluidRow(
    column(6, selectInput("x_iris", "X:", choices= c(unique(colnames(iris))))),
    column(6, selectInput("y_iris", "Y:", choices = c(unique(colnames(iris)))))
   ),
   
   # button to add graph
   # button to remove graph
   fluidRow(
    column(6, actionButton("add_graph", "Add Graph")),
    column(6, actionButton("reset_graph", "Reset Graphs"))
   )
   
  ),
  
  # Show graph
  mainPanel(
   plotOutput("plots")
  )
 )
)


server <- function(input, output) {
 
 # assign graph to reactive value? 
 current_graph <- reactive({ 
  ggplot(iris, aes_string(x = input$x_iris, y = input$y_iris)) + 
   geom_point() 
 })
 
 vals <- reactiveValues(p = 1, gg1 = NULL, gg2 = NULL, gg3 = NULL, gg4 = NULL)
 
 observeEvent(
  input$add_graph,
  {
   req(vals$p <= 4)
   switch (as.character(vals$p),
    "1" = {vals$gg1 = current_graph()},
    "2" = {vals$gg2 = current_graph()},
    "3" = {vals$gg3 = current_graph()},
    "4" = {vals$gg4 = current_graph()}
   )
   vals$p <- vals$p + 1
  }
 )
 
 observeEvent(
  input$reset_graph,
  {
   vals$p <- 1
   vals$gg1 <- NULL
   vals$gg2 <- NULL
   vals$gg3 <- NULL
   vals$gg4 <- NULL
  }
 )
 
 output$plots <- renderPlot({
  plot_grid(plotlist = list(vals$gg1, vals$gg2, vals$gg3, vals$gg4), ncol = 2)
  })
}

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

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.