访问R markdown参数文件的原始文件名

Accessing the original file name of R markdown parameters file

我想为用户提供一种方便的方式来定义输入文件。为此,我在降价中使用了参数功能。如果我“使用参数编织”,我会被要求提供输入文件。

有机会找回文件名吗?因为我在降价期间创建了一些不同的文件,所以我会使用输入文件的文件名作为前缀。到目前为止,文件上传到一个临时目录中,原始文件名丢失了。

如何通过下拉菜单将文件名和位置获取到我的 markdown 文档中?我不希望用户手动写入路径和文件名。

---
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`

您可以让用户 select 在 呈现 文档中的一个文件 embedding a Shiny application。需要注意的是,所有涉及用户 selection 的依赖项的表达式都必须包含在 reactive() 中。如果您正在尝试教授 R,这显然不是最佳选择,但如果它有助于或激发更好的答案,这里有一个例子:

## 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())))
```

除了使用 Shiny 运行 时间,您还可以使用 Shiny Gadgets in combination with customized Knit button behavior (To my understanding, this is largely what's happening when you use 'Knit with Parameters')

您需要两件事:运行 小工具的功能,编织时 运行 的功能。

该小工具本质上是一个闪亮的应用程序,但您可以使用 miniUI 中的专用 UI 元素。作为 mini-app,您可以做的还有很多,但这里是一个基本实现。

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")
  )
  
}

knit 函数将调用小工具,然后在对 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()
  )
  
}

要自定义编织按钮,您需要为文档 YAML header 中的 knit 字段提供一个函数。 R Markdown cookbook 建议您将其保存在一个包中,但我将上述两个函数都放在文件 ("knitFx.R") 中,rmarkdown 文档将获取该文件。

---
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`*

当用户点击“Knit”时,会显示一个UI来选择文件。基于上面的实现,namedatapath 将可以在 rmarkdown 文档中使用。

这是呈现的 HTML 文档: