How to Upload Csv File to Shiny
Uploads and downloads
Transferring files to and from the user is a common feature of apps. You can utilise it to upload information for assay, or download the results every bit a dataset or as a report. This chapter shows the UI and server components that you'll need to transfer files in and out of your app.
Upload
We'll start by discussing file uploads, showing yous the bones UI and server components, and then showing how they fit together in a simple app.
UI
The UI needed to support file uploads is simple: just add fileInput() to your UI.
Like most other UI components, there are only two required arguments: id and label. The width, buttonLabel and placeholder arguments allow you lot to tweak the advent in other means. I won't talk over them here, but you lot tin can read more about them in ?fileInput.
Server
Handling fileInput() on the server is a little more complicated than other inputs. Most inputs return simple vectors, simply fileInput() returns a data frame with four columns:
-
proper noun: the original file name on the user's computer. -
size: the file size, in bytes. By default, the user can but upload files upward to 5 MB. You can increment this limit by setting theshiny.maxRequestSizeselection prior to starting Shiny. For example, to let up to 10 MB runoptions(shiny.maxRequestSize = 10 * 1024^2). -
type: the "MIME type"31 of the file. This is a formal specification of the file type that is usually derived from the extension and is rarely needed in Shiny apps. -
datapath: the path to where the data has been uploaded on the server. Care for this path equally imperceptible: if the user uploads more files, this file may exist deleted. The data is always saved to a temporary directory and given a temporary name.
I call back the easiest manner to understand this data structure is to make a elementary app. Run the post-obit lawmaking and upload a few files to get a sense of what data Shiny is providing. Yous can run into the results later I uploaded a couple of puppy photos (from Section 7.3) in Figure nine.ane.
Note my use of the label and buttonLabel arguments to mildly customise the appearance, and use of multiple = TRUE to allow the user to upload multiple files.
Uploading data
If the user is uploading a dataset, there are two details that y'all demand to be aware of:
-
input$uploadis initialised toNULLon folio load, so you'll needreq(input$upload)to brand sure your code waits until the first file is uploaded. -
The
acceptargument allows you to limit the possible inputs. The easiest style is to supply a character vector of file extensions, similaraccept = ".csv". But thehaveargument is only a suggestion to the browser, and is not always enforced, and then it's good exercise to as well validate it (e.g. Department viii.1) yourself. The easiest way to get the file extension in R istools::file_ext(), but exist aware it removes the leading.from the extension.
Putting all these ideas together gives united states of america the post-obit app where you can upload a .csv or .tsv file and see the first n rows. See it in action in https://hadley.shinyapps.io/ms-upload-validate.
ui <- fluidPage ( fileInput ( "upload", NULL, accept = c ( ".csv", ".tsv" ) ), numericInput ( "n", "Rows", value = 5, min = 1, step = ane ), tableOutput ( "caput" ) ) server <- function ( input, output, session ) { data <- reactive ( { req ( input $ upload ) ext <- tools :: file_ext ( input $ upload $ name ) switch ( ext, csv = vroom :: vroom ( input $ upload $ datapath, delim = "," ), tsv = vroom :: vroom ( input $ upload $ datapath, delim = "\t" ), validate ( "Invalid file; Delight upload a .csv or .tsv file" ) ) } ) output $ caput <- renderTable ( { caput ( information ( ), input $ north ) } ) } Note that since multiple = Faux (the default), input$file will be a single row data frame, and input$file$name and input$file$datapath volition be a length-one graphic symbol vector.
Download
Next, we'll look at file downloads, showing you the basic UI and server components, then demonstrating how you might employ them to allow the user to download information or reports.
Nuts
Over again, the UI is straightforward: use either downloadButton(id) or downloadLink(id) to give the user something to click to download a file. The results are shown in Figure 9.2.
Effigy nine.ii: A download push and a download link
You can customise their advent using the aforementioned form and icon arguments as for actionButtons(), as described in Section 2.2.7.
Dissimilar other outputs, downloadButton() is non paired with a return function. Instead, you use downloadHandler(), which looks something like this:
downloadHandler() has 2 arguments, both functions:
-
filenameshould be a role with no arguments that returns a file name (as a cord). The task of this function is to create the proper noun that will be shown to the user in the download dialog box. -
contentshould exist a function with ane argument,file, which is the path to save the file. The job of this function is to salvage the file in a place that Shiny knows about, then it tin can then send it to the user.
This is an unusual interface, only it allows Shiny to command where the file should be saved (so information technology can exist placed in a secure location) while you still control the contents of that file.
Next we'll put these pieces together to show how to transfer information files or reports to the user.
Downloading data
The following app shows off the basics of information download past allowing you to download any dataset in the datasets parcel equally a tab separated file, Figure 9.iii. I recommend using .tsv (tab separated value) instead of .csv (comma separated values) because many European countries use commas to split up the whole and partial parts of a number (due east.g.1,23 vs one.23). This means they can't utilize commas to carve up fields and instead use semi-colons in and so-called "c"sv files! Y'all can avoid this complexity by using tab separated files, which piece of work the same way everywhere.
ui <- fluidPage ( selectInput ( "dataset", "Pick a dataset", ls ( "bundle:datasets" ) ), tableOutput ( "preview" ), downloadButton ( "download", "Download .tsv" ) ) server <- office ( input, output, session ) { data <- reactive ( { out <- get ( input $ dataset, "packet:datasets" ) if ( ! is.data.frame ( out ) ) { validate ( paste0 ( "'", input $ dataset, "' is not a information frame" ) ) } out } ) output $ preview <- renderTable ( { caput ( data ( ) ) } ) output $ download <- downloadHandler ( filename = function ( ) { paste0 ( input $ dataset, ".tsv" ) }, content = function ( file ) { vroom :: vroom_write ( data ( ), file ) } ) } Annotation the use of validate() to only allow the user to download datasets that are data frames. A better approach would be to pre-filter the list, only this lets you come across another awarding of validate().
Downloading reports
Also as downloading data, you may want the users of your app to download a report that summarises the result of interactive exploration in the Shiny app. This is quite a lot of work, because you also demand to display the aforementioned information in a different format, but it is very useful for loftier-stakes apps.
Ane powerful way to generate such a report is with a parameterised RMarkdown document. A parameterised RMarkdown file has a params field in the YAML metadata:
title : My Document output : html_document params : year : 2018 region : Europe printcode : True data : file.csv Within the document, you tin refer to these values using params$year, params$region etc. The values in the YAML metadata are defaults; you'll generally override them by providing the params argument in a call to rmarkdown::render(). This makes information technology piece of cake to generate many different reports from the same .Rmd.
Here's a simple example adapted from https://shiny.rstudio.com/manufactures/generating-reports.html, which describes this technique in more detail. The key idea is to call rmarkdown::render() from the content argument of downloadHander(). If you want to produce other output formats, just change the output format in the .Rmd, and make sure to update the extension (e.g. to .pdf). Run across it in activeness at https://hadley.shinyapps.io/ms-download-rmd.
ui <- fluidPage ( sliderInput ( "n", "Number of points", 1, 100, 50 ), downloadButton ( "written report", "Generate report" ) ) server <- function ( input, output, session ) { output $ report <- downloadHandler ( filename = "study.html", content = function ( file ) { params <- list (n = input $ n ) id <- showNotification ( "Rendering report...", elapsing = Null, closeButton = Imitation ) on.get out ( removeNotification ( id ), add together = Truthful ) rmarkdown :: render ( "report.Rmd", output_file = file, params = params, envir = new.env (parent = globalenv ( ) ) ) } ) } Information technology'll generally accept at to the lowest degree a few seconds to render a .Rmd, so this is a skillful identify to utilise a notification from Section eight.two.
There are a couple of other tricks worth knowing nigh:
-
RMarkdown works in the current working directory, which will fail in many deployment scenarios (due east.thousand. on shinyapps.io). Yous can work around this by copying the report to a temporary directory when your app starts (i.east. outside of the server part):
report_path <- tempfile (fileext = ".Rmd" ) file.copy ( "report.Rmd", report_path, overwrite = TRUE )Then replace
"report.Rmd"withreport_pathin the call tormarkdown::render(): -
By default, RMarkdown volition render the written report in the current procedure, which means that it will inherit many settings from the Shiny app (like loaded packages, options, etc). For greater robustness, I recommend running
return()in a separate R session using the callr package:render_report <- part ( input, output, params ) { rmarkdown :: render ( input, output_file = output, params = params, envir = new.env (parent = globalenv ( ) ) ) } server <- function ( input, output ) { output $ report <- downloadHandler ( filename = "report.html", content = part ( file ) { params <- listing (due north = input $ slider ) callr :: r ( render_report, list (input = report_path, output = file, params = params ) ) } ) }
Y'all tin meet all these pieces put together in rmarkdown-report/, found inside the Mastering Shiny GitHub repo.
The shinymeta packet solves a related problem: sometimes y'all need to be able to plow the current state of a Shiny app into a reproducible written report that tin exist re-run in the future. Acquire more than near information technology in Joe Cheng'southward useR! 2019 keynote, "Shiny's holy grail: Interactivity with reproducibility".
Instance written report
To finish up, we'll work through a small case study where we upload a file (with user supplied separator), preview it, perform some optional transformations using the janitor packet, by Sam Firke, and then permit the user download it as a .tsv.
To brand information technology easier to sympathise how to employ the app, I've used sidebarLayout() to divide the app into three main steps:
-
Uploading and parsing the file:
ui_upload <- sidebarLayout ( sidebarPanel ( fileInput ( "file", "Data", buttonLabel = "Upload..." ), textInput ( "delim", "Delimiter (exit bare to judge)", "" ), numericInput ( "skip", "Rows to skip", 0, min = 0 ), numericInput ( "rows", "Rows to preview", 10, min = i ) ), mainPanel ( h3 ( "Raw data" ), tableOutput ( "preview1" ) ) ) -
Cleaning the file.
-
Downloading the file.
which get assembled into a single fluidPage():
ui <- fluidPage ( ui_upload, ui_clean, ui_download ) This same organisation makes information technology easier to understand the app:
server <- function ( input, output, session ) { # Upload --------------------------------------------------------- raw <- reactive ( { req ( input $ file ) delim <- if ( input $ delim == "" ) Aught else input $ delim vroom :: vroom ( input $ file $ datapath, delim = delim, skip = input $ skip ) } ) output $ preview1 <- renderTable ( head ( raw ( ), input $ rows ) ) # Clean ---------------------------------------------------------- tidied <- reactive ( { out <- raw ( ) if ( input $ snake ) { names ( out ) <- janitor :: make_clean_names ( names ( out ) ) } if ( input $ empty ) { out <- janitor :: remove_empty ( out, "cols" ) } if ( input $ constant ) { out <- janitor :: remove_constant ( out ) } out } ) output $ preview2 <- renderTable ( head ( tidied ( ), input $ rows ) ) # Download ------------------------------------------------------- output $ download <- downloadHandler ( filename = function ( ) { paste0 ( tools :: file_path_sans_ext ( input $ file $ name ), ".tsv" ) }, content = office ( file ) { vroom :: vroom_write ( tidied ( ), file ) } ) } Exercises
-
Utilise the ambient package past Thomas Lin Pedersen to generate worley noise and download a PNG of it.
-
Create an app that lets you upload a csv file, select a variable, and and then perform a
t.exam()on that variable. After the user has uploaded the csv file, y'all'll demand to utilizeupdateSelectInput()to fill in the available variables. See Section 10.1 for details. -
Create an app that lets the user upload a csv file, select one variable, draw a histogram, and then download the histogram. For an additional claiming, allow the user to select from
.png,.pdf, and.svgoutput formats. -
Write an app that allows the user to create a Lego mosaic from any
.pngfile using Ryan Timpe's brickr package. Once you lot've completed the nuts, add together controls to allow the user to select the size of the mosaic (in bricks), and choose whether to use "universal" or "generic" colour palettes. -
The final app in Section ix.3 contains this one large reactive:
tidied <- reactive ( { out <- raw ( ) if ( input $ ophidian ) { names ( out ) <- janitor :: make_clean_names ( names ( out ) ) } if ( input $ empty ) { out <- janitor :: remove_empty ( out, "cols" ) } if ( input $ constant ) { out <- janitor :: remove_constant ( out ) } out } )Interruption information technology up into multiple pieces and so that (eastward.g.)
janitor::make_clean_names()is non re-run wheninput$emptychanges.
Summary
In this chapter, y'all've learned how to transfer files to and from the user using fileInput() and downloadButton(). Most of the challenges arise either treatment the uploaded files or generating the files to download, so I showed you how to handle a couple of common cases. If I didn't cover your specific challenge hither, yous'll need to apply your ain unique creativity the problem 😄.
The next chapter volition help yous handle a mutual claiming when working with user supplied information: you lot need to dynamically adapt the user interface to better fit the data. I'll start with some simple techniques that are piece of cake to understand and can be applied in many situations, gradually working our way up to fully a dynamic user-interface generated by code.
porterhiscitifted.blogspot.com
Source: https://mastering-shiny.org/action-transfer.html
Belum ada Komentar untuk "How to Upload Csv File to Shiny"
Posting Komentar