Reactively select column name from a table after reactively selecting that table from a list

Viewed 52

I have a shiny application which imports multiple csv/txt files as a list and then outputs the selected table reactively. I would like to be able to reactively select multiple columns within this dataset to ratio to one another but I am having trouble reactively reading the column names of the selected table. A shortened version of my code looks like this.

library(DT)
library(shiny)
library(data.table)

# create dummy CSVs -------------------------------------------------------
DF1 <- data.frame(x = 1:3, y = 2:4)
DF2 <- data.frame(x = 4:6, y = 5:7)
DF3 <- data.frame(x = 7:9, y = 8:10)
DF4 <- data.frame(x = 10:12, y = 11:13)

mapply(
  write.csv,
  x = list(DF1, DF2, DF3, DF4),
  file = list("DF1.csv", "DF2.csv", "DF3.csv", "DF4.csv"),
  row.names = FALSE
)

# shiny app ---------------------------------------------------------------
ui <- fluidPage(sidebarLayout(
  sidebarPanel(
    fileInput(
      "files",
      "Choose File",
      multiple = TRUE,
      accept = c(
        "text/csv",
        "text/comma-separated-values,text/plain",
        ".dp_txt",
        ".is_txt"
      )
    ),

    selectizeInput(
      inputId = "selected_table",
      label = "Table Selection",
      choices = NULL,
      selected = NULL,
      multiple = FALSE
    ),

   selectizeInput("num1", "Numerator (1)", 
                   choices = NULL, 
                   selected = NULL, 
                   multiple = FALSE
                   
    ),
    
    
    selectizeInput("den1", "Denominator (1)", 
                   choices = NULL, 
                   selected = NULL, 
                   multiple = FALSE
    ),
  ),
  mainPanel(DTOutput("table"),
            DTOutput("filtered_table"))
))

server <- function(input, output, session) {
  observeEvent(input$files, {
    freezeReactiveValue(input, "selected_table")
    updateSelectizeInput(session,
                         inputId = "selected_table",
                         choices = input$files$name,
                         server = TRUE)
  })

observeEvent(input$files, {
    freezeReactiveValue(input, "num1")
    updateSelectizeInput(session,
                         inputId = "num1",
                         choices = names(input$files$name),
                         server = TRUE)
    
  })

observeEvent(input$files, {
    freezeReactiveValue(input, "den1")
    updateSelectizeInput(session,
                         inputId = "den1",
                         choices = names(input$files$name),
                         server = TRUE)
    
  })
  
  
  table_list <- reactive({
    req(input$files)
    setNames(lapply(input$files$datapath, function(x) {
      fread(x)
    }),
    input$files$name)
  })
  
  output$table <- renderDT({
    req(table_list(), input$selected_table)
    table_list()[[input$selected_table]]
  }, server = FALSE)
  
}

shinyApp(ui, server)

How can I reactively read the column names and assign them as inputs for the Numerator and Denominator selectizeInput() functions? I appreciate any and all advice!

1 Answers

Why are you using the name attribute of your input file to access its data? Printing its content doesn't bring anything, try yourself:

# In the ui add:
textOutput("testOutput")

# In the server add:
output$testOutput <- renderText(names(input$files$name))

You should use datapath column which you have already read into your table_list() reactive element. Now check if you can retrieve the column names:

# Make a reactive element for the colnames:
colnameReactive <- reactive({
    req(table_list(), input$selected_table)
    dfTmp <- table_list()[[input$selected_table]]
    colnames(dfTmp)
  })

# Now replace testOutput with this:
output$testOutput <- renderText(colnameReactive())

So then you just need to choose the contents of this new reactive element into your updateSelectizeInput(). Hope it helps!

Related