Accessing the original file name of R markdown parameters file - r

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`

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:

Related

How to pass logical parameters with the Quarto R package to the knitr chunk options via a parameterized Quarto document in R

I've provided a minimal reproducible example below. I'm currently trying to use the R quarto package to pass a logical parameter into the Quarto chunk options.
Below is the quarto document, where I created 2 parameters, show_code, and show_plot.
---
title: "Untitled"
format: html
params:
show_code: TRUE
show_plot: TRUE
---
```{r, echo=params$show_code}
summary(cars)
```
```{r, include=params$show_plot}
plot(pressure)
```
This document would render properly via the render button in R studio.
However, when trying to render this document via the quarto_render() function from the R quarto package, this would fail.
library(quarto)
quarto::quarto_render(
input = 'qmd_document.qmd',
output_format = 'html',
output_file = 'qmd_document_with_code.html',
execute_params = list(show_plot = TRUE,
show_code = TRUE)
)
It appears that a character yes is passed instead of the logical TRUE or FALSE to both Chunk 1 and Chunk 2 in the console.
How do I properly pass the logical characters to a parameterized Quarto report chunk options via quarto_render()?
Option 1 (Using chunk options in chunk header)
We can use logical statement in chunk option (as we do in r-markdown).
parameterized_report.qmd
---
title: "Using Parameters"
format: html
params:
show_code: "yes"
show_plot: "yes"
---
```{r, echo=(params$show_code == "yes")}
summary(cars)
```
```{r, include=(params$show_plot == "yes")}
plot(pressure)
```
Then from either r-console/rscript file, we call quarto_render using params "yes" or "no",
quarto::quarto_render(
input = 'parameterized_report.qmd',
output_format = 'html',
output_file = 'qmd_document_with_code.html',
execute_params = list(show_plot = "yes",
show_code = "no")
)
Option 2 (Using YAML syntax chunk option)
Note that, above we have used the chunk option in the chunk header which works fine with knitr engine, but quarto prefers comment-based yaml syntax (i.e. using #|). As per the quarto documentation
Note that if you prefer it is still possible to include chunk options on the first line (e.g. ```{r, echo = FALSE}). That said, we recommend using the comment-based syntax to make documents more portable and consistent across execution engines. Chunk options included this way use YAML syntax rather than R syntax for consistency with options provided in YAML front matter. You can still however use R code for option values by prefacing them with !expr
So following the quarto preferred way, we can use parameters like this,
parameterized_report.qmd
---
title: "Using Parameters"
format: html
params:
show_code: "false"
show_plot: "false"
---
```{r}
#| echo: !expr params$show_code
summary(cars)
```
```{r}
#| include: !expr params$show_plot
plot(pressure)
```
then use quarto_render with "true" or "false"
quarto::quarto_render(
input = 'parameterized_report.qmd',
output_format = 'html',
output_file = 'qmd_document_with_code.html',
execute_params = list(show_plot = "true",
show_code = "true")
)
Lastly, note two things,
here we have used "true" or "false", since echo, include, eval takes value true/false instead of TRUE/FALSE in this comment-based syntax.
Additionally, Since knitr 1.35, knitr engine also supports this comment based syntax. See News from knitr v1.35 to v1.37: Alternative Syntax for Chunk Options

How to run scripts by selecting them from a dropdown menu in R Shiny app?

I am trying to create a shiny app where the user selects an R Markdown file from a drop down menu, and that file is then rendered in the app and the output of that file, a pdf file pops up.
I don't have trouble making a drop down menu, but I am struggling with how to code all of that in the server side of the script.
How would I be able to get a Shiny app to render an R markdown file from a drop down menu? Any help is appreciated.
As discussed in comments:
library(shiny)
shinyApp(
ui = fluidPage(
selectInput("report", "Report", choices=c('Report1.Rmd','Report2.Rmd')),
downloadButton("report", "Generate report")
),
server = function(input, output) {
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.html",
content = function(file) {
# Set up parameters to pass to Rmd document
params <- list(n = 1)
rmarkdown::render(input$report, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
The .Rmd files should be in the working directory.
For example: Report1.Rmd
title: "Dynamic report 1"
output: html_document
params:
n: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot1 of `params$n` random points.
```{r}
plot(rnorm(params$n), rnorm(params$n))
```

R Markdown - Hyperlink outside Rmd file

I am wondering how we can define a hyperlink for R markdown outside Rmd file. Defining a hyperlink inside Rmd file is as easy as typing [hyperlink lable](actual link); but, if on the Rmd file, I am calling some other r-file (e.g., a function) that generates an address to a file, is there a way to transfer this information back to Rmd file to generate a hyperlink there?
Please see example below for more clarification:
Inside Rmd file:
myFun( with some input)
Inside myFun:
myFun <- function( with some input)
some calculations...
return("[click here](C:/myFile.docx)")
The output on the generated html page is:
[1] "[click here] (C:/myFile.docx)"
Which is not a hyperlink!
To define the links outside the rmd file you can use a parameterized report. This allows you to pass values into the rmarkdown document when you compile it. To do this, first create an rmarkdown document that includes the desired parameters, which are declared in the yaml header and then used later in the report. Then, in a separate R script, run the render command (from the rmarkdown package) and pass the desired parameter values.
Here's an example that uses cat or paste to generate the links. For comparison, I've also added a second set of parameters that add different links using the methods in #JohnCoene's answer. I've saved the rmarkdown document as "test.rmd", which is how the document is identified in the render command.
rmarkdown document
---
output: html_document
params:
text1: "add text"
link1: "add URL"
text2: "add text"
link2: "add URL"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r}
# Function to add link
myFun <- function(text, link, inline=TRUE) {
if(inline) {
paste("[", text, "](", link, ")", sep="")
} else {
cat("[", text, "](", link, ")", sep="")
}
}
```
Blah, blah, blah, more text. And here's the link:
```{r, results="asis"}
myFun(params$text1, params$link1, inline=FALSE)
```
Blah, blah, blah, more text. And here's a way to `r myFun(params$text1, params$link1)`.
Or, using the examples from `#JohnCoene's` answer:
With an HTML tag:
```{r, results="asis"}
tg <- function (link, text){
paste0("<a href='", link, "'>", text, "</a>")
}
tg(params$link2, params$text2)
```
With `htmltools`:
```{r}
# install.packages("htmltools")
library(htmltools)
tags$a(
href = params$link2,
params$text2
)
```
Separate R script to render the rmarkdown document
library(rmarkdown)
render(input="test.rmd",
params=list(text1="link to Stackoverflow",
link1="https://stackoverflow.com/questions/52745926/r-markdown-hyperlink-outside-rmd-file",
text2="link to google",
link2="https://google.com"))
Here's what the output html document looks like:
There are multiple solutions, return an html tag or use the htmltools package.
HTML tag
```{r, results="asis"}
tg <- function (link, text){
paste0("<a href='", link"'>", text, "</a>")
}
tg("http://google.com", "link to Google")
```
htmltools
Definitely recommend this way over the other.
```{r}
# install.packages("htmltools")
library(htmltools)
tags$a(
href = "https://google.com",
"Link to Google"
)
```
As mentioned in the question, assuming the output of 'myFun' function is the hyperlink string, here is what worked best for me:
Inside myFun:
myFun <- function()
...some calculations to generate a csv file...
return("C:/myFile.csv")
Inside Rmd file:
```{r, echo=FALSE}
myHyperlink <- myFun()
hyperlink_exists = !is.null(myHyperlink)
```
```{r, eval=hyperlink_exists, results="asis", echo=FALSE}
cat(paste0("The file is saved ","[", "Here", "](", myHyperlink, ")","\n"))
```

How to include html code with reactive MathJax elements in Shiny?

I am working on a shiny app that is intended to help students. It generates solution for each student with some equations using student specific input values.
The problem is that the MathJax equations are rendered as regular text, see the minimal example and this image:
Any idea how dynamic MathJax elements could be rendered properly?
My current approach:
use an rmarkdown document (solu_template.Rmd) with input parameter (params$student) to create student specific markdown file;
render the markdown file and include it in the ui.
Reactive, dynamically changing MathJax elements are feasible as this example shows. However, I would like to use more complex files and keep the convenience of preparing the solution template as an rmarkdown file.
Additional attempts:
direct use of the html file generated by render(), but I do not know how to include it in the ui as a dynamically changing component;
read the generated html file with readLines() and use htmlOutput to display it; no success, just a pile of code.
So, using this approach the question is how to render/display a dynamically changing html file?
All ideas, suggestions are welcome!
app.R
library(shiny)
library(markdown)
shinyApp(
ui = fluidPage(
selectInput("student", "Student:",
choices = c("Student1", "Student2", "Student3")),
actionButton("show_solu", "Run!"),
hr(),
withMathJax(),
htmlOutput("solu")
),
server = function(input, output, session) {
output$solu <- eventReactive(input$show_solu, {
rmarkdown::render("solu_template.Rmd",
quiet = F, clean = F,
params = list(student = input$student))
solu <- renderMarkdown("solu_template.knit.md")
}
)
}
)
solu_template.Rmd
---
title: "Solution"
params:
student: Student1
output:
html_document:
theme: readable
---
```{r, echo = FALSE}
S = list(Student1 = 1, Student2 = 2, Student3 = 3)
s = S[[params$student]]
```
## Heading
Student dependent initial value:
$s = `r s`$
Some nice reasoning which yields to this equation:
$R = s^2 + \sqrt{2} = `r signif(s^2 + sqrt(2), 3)`$
Here is the solution with the renderMarkdown() approach:
The following line should be added to the html code generated by renderMarkdown(), this way the browser will know that the output should be rendered considering MathJax elements:
"<script>MathJax.Hub.Queue(["Typeset", MathJax.Hub]);</script>"
Regarding the above example, this should be added to the end of the server function of app.R:
solu = paste(solu, "<script>MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);</script>")
If you can use knitr I don't see why this wouldn't work. I haven't used 'dynamic-math' but I use a fair amount of notation in Rmd files rendered inside a shiny app used for students. Take a look at the repos linked below and let me know if you have any questions.
https://github.com/vnijs/shiny-site
https://github.com/vnijs/quizr

Chunk reference using knitr, r markdown and pandoc (pander)

I am having trouble trying to reference chunks within a r markdown document which I am trying to convert to .pdf using pandoc.convert.
If I include \label{mylabel} within the text - I can reference this by \ref{mylabel}. However, I thought I might be able to refer to a chunk (or table / figure within a chunk) similarly - but am having no luck.
For instance, for the chunk:
```{r myplot, echo=FALSE, warning=FALSE}
plot(cars)
```
I though I might be able to put \ref{myplot} or \ref{fig:myplot} or even an internal markdown reference [car plot](myplot). The documentation seems to mention that labels are created based on the name of the chunk and these are the formats suggested in relation to similar questions. But none seem to work.
Similarly for tables (which I create using pander) - I have chunks like:
```{r car_sum}
library(pander)
car_summary<-summary(cars)
pander(car_summary, caption = "This is a summary of cars")
```
When converting to .pdf from the .md file using 'pandoc.convert' the tables are given a nice title 'Table 3 This is a summary of cars' and are numbered but I cannot seem to use the label as a reference \ref{car_sum} and it always shows as '??'. Some forums seem to mention that you have to include 'tab:' or 'fig:' before the label name but this still does not work for me.
Can chunk referencing within text be done? If so, what needs to be typed to do this correctly so it works in the final document showing something like 'see Table 2'.
Anything is possible!!
Please see this gist which does what you describe. Just save and knit it to see it in action... For some reason Rpub didn't want to publish it (unknown error).
Testing with converting the knitr generated .html to .pdf via pandoc resulted in working links as well, which is a nice bonus!
The workhorse is::
```{r setup, echo=FALSE, results='hide'}
chunkref <- local({
function(chunklabel) {
sprintf('[%s](#%s)', chunklabel, chunklabel )
}
})
secref <- local({
function(seclabel) {
sprintf('[%s](#%s)', seclabel, seclabel )
}
})
pgref <- local({
function(n)
sprintf('[Page-%i](#Page-%i)', n, n)
})
sec <- local({
function(seclabel) {
sprintf('# <a name="%s"/> %s', seclabel, seclabel )
}
})
pgcount <- local({
pg <- 0
function(inc=T) {
if( inc ) { pg <<- pg + 1 }
return( pg )
}
})
pganchor <- local({
function(doLabel=T) {
if( doLabel) {
sprintf('\n-----\nPage-%i\n<a name="Page-%i"/>\n', pgcount(inc=F), pgcount() )
} else {
sprintf('\n<a name="Page-%i"/>\n', pgcount() )
}
}
})
knit_hooks$set( anchor = function(before, options, envir) {
if ( before ) {
sprintf('<a name="%s"/>\n', options$label )
}
})
knit_hooks$set( echo.label = function(before, options, envir) {
if ( before ) {
sprintf('> %s', options$label )
}
})
knit_hooks$set( pgbreak = function(before, options, envir) {
if ( !before ) {
pganchor();
}
})
````
Which allows for multiple types of references to be created...
Inline: `r sec("Introduction")` then `r secref("Introduction")`
Or
As chunk options:
```{r car-summary, echo=T, warning=FALSE, anchor=T, pgbreak=T, echo.label=F}`
then
`r chunkref("car-summary")`
Even 'top of page' links and 'bottom of page' markers and labels...
Easier solution to referring to figures: put this in the fig.cap field (double \\ to escape the first \):
fig.cap="\\label{mylabel}Caption of my figure."
Then, use \autoref{mylabel} to refer to the figure in the main text.
I am using RStudio with Rmarkdown. Full RMD document:
---
output: pdf_document
---
```{r fig.cap="\\label{mylabel}Caption of my figure."}
plot(1)
```
The generated figure is \autoref{mylabel}.

Resources