I want to provide the user a convenient way to define the input file. For this I am using the parameters functionality in markdown. If I "knit with parameters" I get asked for the input file.
Is there any chance to retrieve the file name? Because I am creating during the markdown some different files and I would use the filename of the input file as a prefix. So far, the file gets uploaded in a temp directory and there, the original file name is lost.
How can I get the file name and location via drop down menu into my markdown document? I don't want the user to write the path and filename manually.
---
title: "Untitled"
date: "11/16/2021"
output: html_document
params:
date_file:
label: "date file"
value: 'dates.tsv'
input: file
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
Filename: `r params$date_file`
To open a new file, click File > New File > R Markdown in the RStudio menu bar. A window will pop up that helps you build the YAML frontmatter for the . Rmd file. Use the radio buttons to select the specific type of output that you wish to build.
To create an R Markdown report, open a plain text file and save it with the extension . Rmd.
To create a new RMarkdown file ( . Rmd ), select File -> New File -> R Markdown... _ in RStudio , then choose the file type you want to create.
You could have users select a file in the rendered document by embedding a Shiny application. The caveat is that all expressions involving dependencies of the user's selection have to be wrapped inside of reactive()
. That is obviously not optimal if you are trying to teach R, but in case it helps or inspires a better answer, here is an example:
## Create a TSV file for testing
cat("x\ty\n1\t2\n3\t4\n", file = "test.tsv")
---
title: "Untitled"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Users can select a file by interacting with an embedded Shiny application.
```{r ui, echo=FALSE}
inputPanel(
fileInput("file", label = "Select a TSV file:", accept = ".tsv")
)
```
User input is stored in a named list-like object `input`,
but this object can only be accessed inside of a _reactive context_.
```{r test1, error=TRUE}
input$file$name
## Name of file selected by user ... _not_ an absolute or relative path
fn <- reactive(input$file$name)
fn
## Absolute path of temporary copy of file
dp <- reactive(input$file$datapath)
dp
```
Don't be misled by how `fn` and `dp` are printed. They are not
strings, but _reactive expressions_. As as a result, they, too,
must be handled inside of a reactive context.
```{r test2}
class(fn)
reactive(class(fn()))
```
Some more examples:
```{r test3, error=TRUE}
## Define reactive data
dd <- reactive(read.table(file = dp(), sep = "\t", header = TRUE))
## Do stuff with it
reactive(names(dd()))
reactive(nrow(dd()))
## Write object to file in _working directory_
reactive(saveRDS(dd(), file = sub("tsv$", "rds", fn())))
```
As alternative to using the Shiny runtime, you can also use Shiny Gadgets in combination with customized Knit button behavior (To my understanding, this is largely what's happening when you use 'Knit with Parameters')
You'll need two things: a function to run the gadget, a function to run when knitting.
The gadget is essentially a Shiny app, but you can use specialized UI elements from miniUI
. As a mini-app, there's a lot more you can do, but here's a basic implementation.
library(shiny)
library(miniUI)
get_file_param <- function(){
ui <- miniPage(
miniContentPanel(
fileInput("dateFile", "Date File")
# ...Other UI elements to collect other parameters...
),
miniTitleBar(
NULL,
right = miniButtonBlock(
miniTitleBarCancelButton(),
miniTitleBarButton("done", "Done", primary = TRUE))
)
)
server <- function(input, output, session){
# Handle the Done button being pressed
observeEvent(input$done, {
# Return the full file info data.frame. See ?shiny::fileInput
stopApp(input$dateFile)
})
}
runGadget(
app = ui,
server = server,
viewer = paneViewer() #dialogViewer("Knit with Parameters - Custom UI")
)
}
The knit function will call the gadget and then use its output in a call to rmarkdown::render
knit_with_file <- function(input, ...){
fileInfo <- get_file_param()
rmarkdown::render(
input,
params = list(
date_file = list(name = fileInfo$name, datapath = fileInfo$datapath)
),
envir = globalenv()
)
}
To customize the knit button, you provide a function to the knit
field in the document YAML header. The R Markdown cookbook suggest you keep this in a package, but I put both of the above functions in file ("knitFx.R"), which the rmarkdown document will source.
---
title: "Untitled"
date: "11/16/2021"
output: html_document
params:
date_file: 'dates.tsv'
knit: (function(input, ...) {
source("knitFx.R")
knit_with_file(input, ...)
})
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
**Original Name of Uploaded File**: *`r params$date_file$name`*
**Local Temp File Path**: *`r params$date_file$datapath`*
When the user clicks "Knit", a UI will be displayed to choose the file. Based on implementation above, the name
and datapath
will then be available to use in the rmarkdown document.
Here's the rendered HTML document:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With