Search code examples
rshinysubsetshiny-reactivity

How to efficiently subset a dataframe in R Shiny?


In the below example code I reactively subset the mtcars dataframe inside the renderPlot() function. However, in my larger App with many render functions in the server section I am having to repeat the same rv$x[1:input$samples], etc., over and over in many places. How would I apply this subsetting instead "at the top", into the rv <- reactiveValues(...) function itself or equivalent "master function"? I tried subsetting inside the reactiveValues() and got the message "Warning: Error in : Can't access reactive value 'samples' outside of reactive consumer. Do you need to wrap inside reactive() or observer()?" I assumed incorrectly that the reactiveValues() function is a "reactive consumer".

If someone can answer this basic understanding question, please explain the logic for correctly subsetting "at the top" because I am getting very embarrassed by my repeated questions about Shiny reactivity.

library(shiny)

ui <- fluidPage(
  sliderInput('samples','Nbr of samples:',min=2,max=32,value=16),
  plotOutput("p")
)

server <- function(input, output, session) {
  
  rv <- reactiveValues(
    x = mtcars$mpg,
    y = mtcars$wt
  )
  
  output$p <- renderPlot({plot(rv$x[1:input$samples],rv$y[1:input$samples])})

}

shinyApp(ui, server)

Solution

  • There are multiple ways you can handle this.

    Here is one way to create new subset reactive values inside observe.

    library(shiny)
    
    ui <- fluidPage(
      sliderInput('samples','Nbr of samples:',min=2,max=32,value=16),
      plotOutput("p")
    )
    
    server <- function(input, output, session) {
      
      rv <- reactiveValues(
        x = mtcars$mpg,
        y = mtcars$wt
      )
      
      observe({
        rv$x_sub <- rv$x[1:input$samples]
        rv$y_sub <- rv$y[1:input$samples]
      })
      
      output$p <- renderPlot({plot(rv$x_sub,rv$y_sub)})
      
    }
    
    shinyApp(ui, server)
    

    enter image description here