R Markdown - Hyperlink outside Rmd file - r

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

Related

Accessing the original file name of R markdown parameters file

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:

knitr: how to get and override chunk options from inside a chunk

I have 2 questions about knitr chunk options:
1) Is it possible to override knitr chunk options from inside a chunk of code so that the options were applied in the same chunk? e.g. write something like the following lines and get result as-is:
```{r, results= "markup"}
knitr::opts_chunk$set(results= "asis")
for (i in 1:5)
print("# This text should be printed 'as-is'")
```
p.s. I'm familiar with knitr::asis_output.
2) Is it possible to get chunk options from inside a chunk? E.g., to use code like:
```{r}
knitr::opts_chunk$get("results")
```
And get string markup.
```{r, results='asis'}
knitr::opts_chunk$get("results")
```
And get string asis.
Unfortunately, knitr::opts_chunk$get("results") gets global options, and not the ones of a current chunk.
1) Printings can be customized using functions knitr::normal_print and knitr::asis_output (as you mentionned). For instance :
```{r, results='markup'}
knitr::asis_output(replicate(5, "# This text should be printed 'as-is'\n"))
print("# This text should be printed 'normal'")
```
and alternatively
```{r, results='asis'}
for (i in 1:5)
cat("# This text should be printed 'as-is'\n")
knitr::normal_print("# This text should be printed 'normal'\n")
```
2) Current chunk options can be retrieved using knitr::opts_current$get(). Use :
```{r, results='asis'}
knitr::opts_current$get("results")
```
and get string asis

wrapping figure with latex environment in knitr/rmarkdown with hooks

I'd like to wrap figures created with knitr and rmarkdown in a "wrapfigure" environment using hooks. However, when running the minimal example below, the figure chunk only gets compiled into a markdown picture:
\begin{wrapfigure}{R}{0.3\textwidth}
![](test_files/figure-latex/unnamed-chunk-2-1.pdf)
\end{wrapfigure}
and not the expected:
\begin{wrapfigure}{R}{0.3\textwidth}
\includegraphics{test_files/figure-latex/unnamed-chunk-2-1.pdf}
\end{wrapfigure}
Minimal example:
---
header-includes:
- \usepackage{wrapfig}
output:
pdf_document:
keep_tex: TRUE
---
```{r}
library(knitr)
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
"\\begin{wrapfigure}{R}{0.3\\textwidth}"
} else {
"\\end{wrapfigure}"
}
})
```
```{r, wrapf=TRUE}
library(ggplot2)
qplot(cars$speed, cars$dist)
```
pandoc is responsible for converting the markdown document to a TEX document. As pandoc doesn't touch between \begin{…} and \end{…} the markdown syntax for the image is not being converted to TEX syntax.
You could …
Hide the plot (fig.show = 'hide') and use something along the lines of cat("\includegraphics{figure/unnamed-chunk-2-1.pdf}").
Hide the plot as above and include some magic in the hook that saves the cat.
Write RNW instead of RMD if you want PDF output.
Here's an example for option 2:
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
return("\\begin{wrapfigure}{R}{0.3\\textwidth}")
} else {
output <- vector(mode = "character", length = options$fig.num + 1)
for (i in 1:options$fig.num) {
output[i] <- sprintf("\\includegraphics{%s}", fig_path(number = i))
}
output[i+1] <- "\\end{wrapfigure}"
return(paste(output, collapse = ""))
}
})
This hook can be used with wrapf = TRUE and fig.show = "hide". (Moreover, you need to add \usepackage{graphics} to header-includes.)
But note that I would not do it! Too many things can go wrong in more complex settings. Think of cache, captions, labels, cache (again!) …
Therefore, if it is really necessary to control the typesetting of the PDF, I recommend writing RNW (option 3).

set fig.cap to options$label

How can I programmatically set a figure caption in a knitr hook?
I'd like to set the figure caption, if not explicitly defined, to the chunk label. I've read the knitr docs on options, options, and hooks, and though I think I understand the mechanisms at play, I can't get it to work.
My use-case that perhaps justifies this behavior: my work-flow recently adapted to start my data and visualization exploration in Rmd files. I'll use chunks for cleaning, subsetting, etc, and then a sample chunk for each visualization. This is quick and dirty, meaning minimal markdown. When I look over the report (typically rendered into PDF), I'll look at a figure and want to go straight to the source for it. Though text before/after the figure can provide insight, due to LaTeX figure rules it is not a sure thing. Counting figure numbers is feasible, but not "easy" (and becomes problematic with many figures). Captions are always with the figure, so it'd be great if I can default to filling the caption with the chunk label. (Yes, it's a little lazy of me.)
The MWE is below.
The hook code ran just fine; the returned strings in the hook appeared correctly. However, the figure caption did not change. Exception: when there is a chunk with an undefined fig.cap, all subsequent chunks have their caption set to the first un-captioned chunk name; this doesn't surprise me due to the global nature of opts_chunk, so that's out.
I suspect it might be related to "output hooks" vice "chunk hooks," but this really is a per-chunk thing and I do not want to modify the plot, just set the caption.
MWE:
---
title: "Document Title"
author: "My Name"
output:
pdf_document:
fig_caption: yes
---
# Header
```{r setup}
knit_hooks$set(autocap = function(before, options, envir) {
if (before) {
if (is.null(options$fig.cap)) {
options$fig.cap <- options$label
knitr::opts_current$set(fig.cap = options$label)
knitr::opts_chunk$set(fig.cap = options$label) # wrong!
paste('Set: `', options$label, '`, `',
knitr::opts_current$get('fig.cap'), '`', sep = '')
} else {
paste('Kept: `', options$fig.cap, '`', sep = '')
}
}
})
opts_chunk$set(autocap = TRUE)
```
## No Plot
```{r textOnly}
1+1
```
## Caption Already Set
```{r someplot, fig.cap='someplot caption'}
plot(0)
```
## Caption Not Set
```{r anotherPlot}
plot(1)
```
Is it ok like this ? I simply modify the knitr internal function .img.cap function which can be found here.
```{r}
.img.cap = function(options) {
if(is.null(options$fig.cap)) options$label else options$fig.cap
}
assignInNamespace(".img.cap", .img.cap, ns="knitr")
```
Does it help ?
```{r}
library(knitr)
knit_hooks$set(htmlcap = function(before, options, envir) {
if(!before) {
caption <- ifelse(is.character(options$htmlcap), options$htmlcap, options$label)
paste('<p class="caption">', caption, "</p>", sep="")
}
})
```
```{r Hello, htmlcap=TRUE}
library(ggplot2)
ggplot(diamonds,aes(price,carat)) + geom_point()
```
```{r, htmlcap="Hello again"}
ggplot(diamonds,aes(price,carat)) + geom_point()
```

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