johnny utah
johnny utah

Reputation: 279

shiny selecting specific columns from uploaded data frame

I have merged different sources of code to make an app that allows one to upload a file (data frame).

However, beyond this I would also like to make it possible to select specific columns from the data frame and analyse them. This is difficult however as one must predefine the given data frame in order to be able to refer to it in the ui.R script.... So when a previously undefined data frame is uploaded to the site, one can not revere to it in the ui.R as it is defined in the server....

predefined variables

vchoices <- 1:ncol(mtcars)
names(vchoices) <- names(mtcars)

ui.R

    runApp(
      ui = basicPage(
        h2('The uploaded file data'),
        dataTableOutput('mytable'),
        fileInput('file', 'Choose info-file to upload',
                  accept = c(
                    'text/csv',
                    'text/comma-separated-values',
                    'text/tab-separated-values',
                    'text/plain',
                    '.csv',
                    '.tsv'
                  )
        ),
        actionButton("choice", "incorporate external information"),

        selectInput("columns", "Select Columns", choices=vchoices, inline = T),
        #notice that the 'choices' in selectInput are set to the predefined 
        #variables above whereas I would like to set them equal to the 
        #not yet defined uploaded file below in server.R

        tableOutput("table_display")
      ))

Notice that the 'choices' in selectInput are set to the predefined variables above whereas I would like to set them equal to the not yet defined uploaded file below in server.R

server.R

  server = function(input, output) {

      info <- eventReactive(input$choice, {
        inFile <- input$file
        if (is.null(inFile))
          return(NULL)
        isolate(f<-read.table(inFile$datapath, header = T,
                               sep = "\t"))
        f
      })
      output$table_display<-renderTable({
        f<-info()
        f<-subset(f, select=input$columns) #subsetting takes place here
        head(f)
      })
    }

Does anyone know of a way to refer to a variable that's defined in in the server, in the ui and thus allow for interactive manipulation?

Upvotes: 2

Views: 6042

Answers (1)

Michal Majka
Michal Majka

Reputation: 5471

You can use a family of functions update*Input - in this case updateSelectInput. Its first argument has to be session and you also have to add session to server <- function(input, output) to be able to update your widget.

You could make an update of the widget immediately after clicking on the actionButton - so, you had to use updateSelectInput within eventReactive.


Let's take a look how we can do that:

First, you can save the names of columns of the new uploaded dataset in a variable, say, vars and then pass it to the function updateSelectInput. (The choices of the selectInput are initially set to NULL - we don't need to specify them before because they are going to be updated anyway)

info <- eventReactive(input$choice, {
    inFile <- input$file
    # Instead # if (is.null(inFile)) ... use "req"
    req(inFile)

    # Changes in read.table 
    f <- read.table(inFile$datapath, header = input$header, sep = input$sep, quote = input$quote)
    vars <- names(f)
    # Update select input immediately after clicking on the action button. 
    updateSelectInput(session, "columns","Select Columns", choices = vars)

    f
  })

I've added a small upload interface to your code.

The other way would be to define widgets on the server side and then to pass them to the client side via renderUI function. You can find here an example.


Full example:

library(shiny)

ui <- fluidPage(
  h2('The uploaded file data'),
  dataTableOutput('mytable'),
  fileInput('file', 'Choose info-file to upload',
            accept = c(
              'text/csv',
              'text/comma-separated-values',
              'text/tab-separated-values',
              'text/plain',
              '.csv',
              '.tsv'
            )
  ),
  # Taken from: http://shiny.rstudio.com/gallery/file-upload.html
  tags$hr(),
  checkboxInput('header', 'Header', TRUE),
  radioButtons('sep', 'Separator',
               c(Comma=',',
                 Semicolon=';',
                 Tab='\t'),
               ','),
  radioButtons('quote', 'Quote',
               c(None='',
                 'Double Quote'='"',
                 'Single Quote'="'"),
               '"'),
  ################################################################

  actionButton("choice", "incorporate external information"),

  selectInput("columns", "Select Columns", choices = NULL), # no choices before uploading 

  tableOutput("table_display")
)

server <- function(input, output, session) { # added session for updateSelectInput

  info <- eventReactive(input$choice, {
    inFile <- input$file
    # Instead # if (is.null(inFile)) ... use "req"
    req(inFile)

    # Changes in read.table 
    f <- read.table(inFile$datapath, header = input$header, sep = input$sep, quote = input$quote)
    vars <- names(f)
    # Update select input immediately after clicking on the action button. 
    updateSelectInput(session, "columns","Select Columns", choices = vars)

    f
  })

  output$table_display <- renderTable({
    f <- info()
    f <- subset(f, select = input$columns) #subsetting takes place here
    head(f)
  })
}
shinyApp(ui, server)

Upvotes: 6

Related Questions