Search code examples
rshinyshiny-reactivity

Reactively pull data from list objects in Shiny


I am trying to extract data stored within lists. I have studied basic reactivity but I am now stuck as I don't know how to handle a list within the list.

If I run the app, I want to be able to look at the underlying dataframes for each list.

For example, If I select "output_2" in the drop down on the left, then I expect to see the dataframes on the right hand side of the page (which go from 2:20).

library(tidyverse)
library(shiny)
library(DT)

# create dummy data frames
df1.1 <- data.frame(Item = 1:10, Amount = 1:10)
df1.2 <- data.frame(Item = 1:10, Amount = 1:10)
df1.3 <- data.frame(Item = 1:10, Amount = 1:10)

df2.1 <- data.frame(Item = 2:20, Amount = 2:20)
df2.2 <- data.frame(Item = 2:20, Amount = 2:20)
df2.3 <- data.frame(Item = 2:20, Amount = 2:20)

df3.1 <- data.frame(Item = 3:30, Amount = 3:30)
df3.2 <- data.frame(Item = 3:30, Amount = 3:30)
df3.3 <- data.frame(Item = 3:30, Amount = 3:30)

# create list with dummy dfs
dummy_list1 <- list(df1.1 = df1.1,
                    df1.2 = df1.2,
                    df1.3 = df1.3)

dummy_list2 <- list(df2.1 = df2.1,
                    df2.2 = df2.2,
                    df2.3 = df2.3)

dummy_list3 <- list(df3.1 = df3.1,
                    df3.2 = df3.2,
                    df3.3 = df3.3)

# create data 
previous_data <- list(output_1 = dummy_list1,
                      output_2 = dummy_list2,
                      output_3 = dummy_list3)

previous_data_names <- previous_data %>% names()  

# Define UI for the app

ui <- fluidPage(
  titlePanel("Output Selector App"),
  sidebarLayout(
    sidebarPanel(
      selectInput("dataset", "Choose a dataset:", 
                  choices = previous_data_names)
    ),
    mainPanel(
      navlistPanel(
        tabPanel("df_1", dataTableOutput("df_1")),
        tabPanel("df_2", dataTableOutput("df_2")),
        tabPanel("df_3", dataTableOutput("df_3")),
      )
    )
  )
)


# Define server logic for the app
server <- function(input, output, session) {
  
  output$df_1 <- renderDataTable(
    datatable(df1.1)
  )
  
  output$df_2 <- renderDataTable(
    datatable(df1.2)
  )
  
  output$df_3 <- renderDataTable(
    datatable(df1.3)
  )
  
}


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

Solution

  • You need to refer to previous_data, and input$dataset in your render functions:

    For example:

      output$df_1 <- renderDataTable(datatable(previous_data[[input$dataset]][[1]]))
      output$df_2 <- renderDataTable(datatable(previous_data[[input$dataset]][[2]]))
      output$df_3 <- renderDataTable(datatable(previous_data[[input$dataset]][[3]]))
    

    Or, equivalently:

      d <- reactive(previous_data[[input$dataset]])
      for(i in 1:3) output[[paste0("df_",i)]] <- renderDataTable(datatable(d()[[i]]))