0

all.

I would like to create a shiny script to perform some analysis. One of the first steps is to ensure that people have the correct input. There is one major input that are several files in a folder, 2 mandatory tsv/txt inputs and 3 optional tsv/txt ones. The optional ones are independent, meaning I could have any combination of them present, or none.

Each tsv/txt have some information in lines that are supposed to be added as a column to my output, a dataframe of sorts.

As of right now, my code is able to receive the mandatory inputs and show the output with the correct row names and the 2 mandatory input information as columns.

I am struggling to find a way to process the optional inputs. I don't think the req() statement will do, because it may hold the execution while it is waiting for one of the optional inputs that may never come.

I thought about placing a send button and watch for the action with observeEvent() but it will throw an error for being inside renderTable().

Well, this is my code. The auxiliary functions are weird, in my real code they are processing the files using a very specific package that I took out of this minimal working example. I commented the part that is not working. Input test files are here.

library(shiny)

read_and_rename_my_files <- function(input_from_shiny) {
  n_rows <- length(input_from_shiny$name)
  cel_files <- data.frame(1:n_rows)
  rownames(cel_files) <- input_from_shiny$name
  
  return(cel_files)
}

read_file_content_from_column <- function(path_file, 
                                          i_col = 1){
  if (file.exists(path_file)) {
    content <- read.table(file = path_file,
                          header = F)[, i_col]
    return(content)
  } else {
    stop(sprintf(fmt = 'File >%s< not found.',
                 path_arq))
  }
}

edit_mydata <- function(mydata_obj,
                        path_arq,
                        n_col_mydata,
                        name_col_mydata){
  
  content <- read_file_content_from_column(path_file = path_arq)
  
  mydata_obj[, n_col_mydata] <- content
  colnames(mydata_obj)[n_col_mydata] = name_col_mydata
  return(mydata_obj)
}

ui <- fluidPage(
  navbarPage(title = "Stack overflow is great", 
             tabPanel(title = "Data Input", 
                      fluid = TRUE, 
                      sidebarLayout(
                        sidebarPanel = sidebarPanel(width = 4,
                                                    
                                                    # File uploads
                                                    fileInput(inputId = 'main_input', 
                                                              label = 'the content of the provided folder: use ctrl + A to add all files.', 
                                                              multiple=TRUE, 
                                                              accept = c("text/csv",
                                                                         "text/comma-separated-values,text/plain",
                                                                         ".csv")),
                                                    fileInput(inputId = "mandatory_input1", 
                                                              label = "Choose TSV file with sample names",
                                                              multiple = FALSE,
                                                              accept = c("text/csv",
                                                                         "text/comma-separated-values,text/plain",
                                                                         ".csv")),
                                                    fileInput(inputId = "mandatory_input2", 
                                                              label = "Choose TSV file with experimental conditions",
                                                              multiple = FALSE,
                                                              accept = c("text/csv",
                                                                         "text/comma-separated-values,text/plain",
                                                                         ".csv")),
                                                    tags$hr(),
                                                    
                                                    fileInput(inputId = "optional_input1", 
                                                              label = "Optional: choose TSV file with another grouping variable",
                                                              multiple = FALSE,
                                                              accept = c("text/csv",
                                                                         "text/comma-separated-values,text/plain",
                                                                         ".csv")),
                                                    textInput(inputId = "optional_input1_name",
                                                              label = "Input grouping variable name",
                                                              #value = "group",
                                                              placeholder = "Ex: ageGroup")#,
                                                    
                        ),
                        # Main Panel for dataInput
                        mainPanel = mainPanel(
                          tableOutput(outputId = "contents")
                        )))))

server <- function(input, output) {
  
  output$contents <- renderTable(rownames = T, 
                                 expr = {
                                   
                                   req(input$main_input)
                                   files.cel <- read_and_rename_my_files(input$main_input)
                                   
                                   req(input$mandatory_input1)
                                   files.cel <- edit_mydata(mydata_obj = files.cel,
                                                            path_arq = input$mandatory_input1$datapath,
                                                            n_col_mydata = 1,
                                                            name_col_mydata = "Sample_names")
                                   
                                   req(input$mandatory_input2)
                                   files.cel <- edit_mydata(mydata_obj = files.cel,
                                                            path_arq = input$mandatory_input2$datapath,
                                                            n_col_mydata = 2,
                                                            name_col_mydata = "Conditions")

                                   # observeEvent(eventExpr = input$groupingButton,
                                   #              handlerExpr = {
                                   #                pData(files.cel) <- edit_pdata(pdata_obj = pData(files.cel),
                                   #                                               path_arq = input$GROUPING_FILE$datapath,
                                   #                                               n_col_pdata = ncol(pData(files.cel)) + 1,
                                   #                                               name_col_pdata = "Grouping")})
                                   
                                 }
  ) 
}

shinyApp(ui = ui, server = server)


All suggestions are appreciated. I am open to redesigning the whole thing. Thank you all in advance.

Bonus question: I have a textbox input to receive the name of the optional input 1. Any ideas on how to use that too?

  • I'd break it down into separate steps. 1) create reactive objects to store mandatory and optional files 2) tohse reactive would be populated in `observeEvent` conneted to specific fileInput 3) rendering a table could be triggered by separate button that would be observed separately. – Dominik Żabiński Sep 23 '22 at 16:18
  • `req` is powered by a handy function called `isTruthy`. Instead of breaking out of your reactive expression it just returns `FALSE` for inputs that would fail `req`. It's useful for optional parameters like this. – SmokeyShakers Sep 23 '22 at 19:51

0 Answers0