Validate Column Names in R Csv Upload
At the very bottom is now posted the complete resolved code, reflecting the solution offered by M. Jagan. This code offers the total bicycle of both data uploads (with robust data validation) and downloads of user inputs. Yous can encounter how the try()
function "tests" the upload to avoid unnecessarily crashing the App.
When running the below code, the user can upload and download input data. The user tin can download and save inputs, and afterwards remember those inputs via upload. I'm trying to better the upload validation because in reality it will be very like shooting fish in a barrel for the user to select an incorrect file and I'd rather flag with a warning rather than accept the App crash like it does now.
All downloads are saved as a ii-column matrix with headers of 10 and Y. That (and the fact that it's a CSV) are my key upload validations per the beneath code. The App correctly downloads and uploads CSV data as shown in image 1 (download) and image 2 (upload) below, but crashes when it tries uploading incorrectly formatted CSV data per image three below.
So my questions are:
- How exercise I specify which columns in the csv file to await for the "X" and "Y" headers? Currently it reads everywhere for X and Y headers. I tried
read.csv(...colClasses=c(NA, NA)))
as shown beneath, I likewise triedread.csv(...)[ , ane:2]
and neither i works. - More than generally, is there a style to abort the upload if it would otherwise cause an error or crash? Sort of similar
if(iserror(...))
in Excel - OK now I'm pushing it, delight feel free to ignore this if this is too much. Any manner to movement the upload alert into
modalDialog
? I can always move this to another post if I can't figure it out, after resolving the in a higher place.
MWE code:
library(dplyr) library(shiny) library(shinyMatrix) interpol <- function(a, b) { # a = periods, b = matrix inputs c <- rep(NA, a) c[1] <- b[i] c[a] <- b[two] c <- approx(seq_along(c)[!is.na(c)], c[!is.na(c)], seq_along(c))$y render(c) } ui <- fluidPage( sidebarLayout( sidebarPanel( fileInput("file1", "Optionally choose input file (csv)", accept = ".csv"), sliderInput('periods', 'Periods to interpolate over:', min=one, max=ten, value=x), matrixInput("matrix1", value = matrix(c(1,5), ncol = 2, dimnames = list("Interpolate",c("10","Y")) ), cols = list(names = Truthful), class = "numeric" ), downloadButton("download") ), mainPanel( tableOutput("contents"), plotOutput("plot") ) ) ) server <- function(input, output, session) { input_file <- reactive({ file <- input$file1 ext <- tools::file_ext(file$datapath) req(file) if(is.null(file)) render(Cipher) file_contents <- read.csv(file$datapath,header=TRUE,colClasses=c(NA, NA)) required_columns <- c('Ten','Y') column_names <- colnames(file_contents) shiny::validate( demand(ext == "csv", "Incorrect file type"), demand(required_columns %in% column_names, "Incorrect file type") ) file_contents }) output$contents <- renderTable({ input_file() }) data <- part(){ tibble( 10 = seq_len(input$periods), Y = interpol(input$periods,matrix(c(input$matrix1[1,one],input$matrix1[1,ii]))) ) } output$plot<-renderPlot({plot(data(),type="l",xlab="Periods (Ten)", ylab="Interpolated Y values")}) observeEvent(input$file1,{ updateMatrixInput(session, inputId = "matrix1", value = matrix(as.matrix(input_file()), ncol=ii, dimnames = list("Interpolate",c("X","Y")) ) ) }) output$download <- downloadHandler( filename = function() { paste("Inputs","csv",sep=".") }, content = function(file) { write.csv(input$matrix1, file,row.names=Faux) } ) } shinyApp(ui, server)
At present the resolved code:
library(dplyr) library(shiny) library(shinyFeedback) library(shinyMatrix) nms <- c("10", "Y") # < Matrix variable names (headers) interpol <- function(a, b) { # < a = periods, b = matrix inputs c <- rep(NA, a) c[1] <- b[one] c[a] <- b[2] c <- approx(seq_along(c)[!is.na(c)], c[!is.na(c)], seq_along(c))$y return(c) } ui <- fluidPage( useShinyFeedback(), sidebarLayout( sidebarPanel( fileInput("file", "Optionally choose input file (csv)", take = ".csv"), sliderInput('periods', 'Periods to interpolate over:', min=1, max=10, value=10), matrixInput("matrix1", "Values to interpolate:", value = matrix(c(one,five),ncol = 2,dimnames = list(NULL,nms)), cols = listing(names = TRUE), rows = listing(names = False), class = "numeric" ), downloadButton("download") ), mainPanel( tableOutput("contents"), plotOutput("plot"), verbatimTextOutput("verb") ) ) ) server <- function(input, output, session) { uploadData <- reactive({ req(input$file) validate(need(identical(tools::file_ext(input$file$datapath),"csv"),"Invalid extension")) try(read.csv(input$file$datapath, header = TRUE)) }) observeEvent(uploadData(), { if(is.data.frame(uploadData()) && all(nms %in% names(uploadData())) && all(vapply(uploadData()[nms],is.numeric,NA))){ updateMatrixInput(session,"matrix1",every bit.matrix(uploadData()[nms])) hideFeedback("file") } else { showFeedbackWarning("file", "Invalid upload.") } }) information <- function(){ tibble( X = seq_len(input$periods), Y = interpol(input$periods,matrix(c(input$matrix1[1,1],input$matrix1[ane,2]))) ) } output$plot<-renderPlot({plot(data(),blazon="50",xlab="Periods (X)", ylab="Interpolated Y values")}) output$verb <- renderPrint(class(uploadData())) output$download <- downloadHandler( filename = function() { paste("Inputs","csv",sep=".") }, content = function(file) { write.csv(input$matrix1, file,row.names=FALSE) } ) } shinyApp(ui, server)
Source: https://stackoverflow.com/questions/70045163/how-to-more-completely-validate-csv-file-when-uploading-to-shiny-app