rshinyredundancy

How to avoid repeating the same procedure multiple times in Shiny app


I have written a Shiny app where I am sampling from a poisson distribution. I have rewritten the function for each time I want to output a plot or summary of the data. I would rather only use the function once and then have all plots and summaries refer to the single time the function was called, otherwise the results will not be identical across the outputs. When I tried to call the function once and store the results as a variable to be used by ggplot I got the error that ggplot cannot use reactive data and I was not able to coerce it into a data frame.

I tried variations of:

mydata <- reactive({
  x <- input$x
  y <- input$y
  z <- input$z
  Muts <- as.data.frame(rpois(100,(x*y*z)))
  Muts
})

However they did not work, as ggplot could not use the input. I think I am not using the reactive function correctly. Any help to reduce the redundancy in the code and ensure that the plots and summary are all using the same single underlying data are much appreciated. Thank you in advance.

My current code:

server.R

library(shiny)
library(ggplot2)

# Define server logic required to draw a histogram
function(input, output) {




  output$distPlot <- renderPlot({

    x <- input$x
    y <- input$y
    z <- input$z
    Muts <- as.data.frame(rpois(100,(x*y*z)))


    # draw the density plot

    ggplot(Muts, aes(Muts)) + geom_density() 

  })

  output$distPlot2 <-renderPlot({

    x <- input$x
    y <- input$y
    z <- input$z
    Muts <- as.data.frame(rpois(100,(x*y*z)))



    Muts <- as.data.frame(Muts)

    ggplot(Muts, aes(Muts)) + geom_histogram() 

  })

  output$summary <- renderPrint({
    x <- input$x
    y <- input$y
    z <- input$z
    Muts <- as.data.frame(rpois(100,(x*y*z)))

    summary(Muts)
  })


}

Solution

  • Your idea was right, but a reactive is essentially a cached function that need to be called to retrieve it's return values, so mydata() is correct and mydata just return the function itself (not the return values).

    library(shiny)
    library(ggplot2)
    
    # Define UI for application
    ui <- fluidPage(
       
       # Application title
       titlePanel(""),
       
       # Sidebar with a slider input for number of bins 
       sidebarLayout(
          sidebarPanel(
             sliderInput("x",
                         "Number of bins:",
                         min = 1,
                         max = 50,
                         value = 30),
             sliderInput("y",
                         "Number of bins:",
                         min = 1,
                         max = 50,
                         value = 30),
             sliderInput("z",
                         "Number of bins:",
                         min = 1,
                         max = 50,
                         value = 30)
          ),
          
          # Show a plot of the generated distribution
          mainPanel(
             plotOutput("distPlot"),
             plotOutput("distPlot2"),
             verbatimTextOutput("summary")
          )
       )
    )
        
    # Define server logic
    server <- function(input, output) {
      
      mydata <- reactive({
        x <- input$x
        y <- input$y
        z <- input$z
        Muts <- data.frame(x = rpois(100,(x*y*z)))
        Muts
      })
      
      
      output$distPlot <- renderPlot({
        Muts <- mydata()
        ggplot(Muts, aes(x = x)) + geom_density() 
      })
      
      output$distPlot2 <-renderPlot({
        Muts <- mydata()
        ggplot(Muts, aes(x = x)) + geom_histogram() 
      })
      
      output$summary <- renderPrint({
        Muts <- mydata()
        summary(Muts)
      })
      
      
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)