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?