user964689
user964689

Reputation: 822

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)
  })


}

Upvotes: 1

Views: 2065

Answers (2)

shosaco
shosaco

Reputation: 6155

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)

Upvotes: 2

MrFlick
MrFlick

Reputation: 206167

Just make sure to call mydata() to actually get the value of your reactive object.

library(shiny)
library(ggplot2)


ui <- fluidPage(
numericInput("x", "x", 2), numericInput("y", "y", 2), numericInput("z", "z", 2),
plotOutput("distPlot"), plotOutput("distPlot2"))

server <- function(input, output) {

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


  output$distPlot <- renderPlot({

    ggplot(mydata(), aes(x)) + geom_density() 

  })

  output$distPlot2 <-renderPlot({

    ggplot(mydata(), aes(x)) + geom_density() 

  })
}

runApp(list(ui=ui, server=server))

Upvotes: 3

Related Questions